package cn.stylefeng.guns.modular.hx.storage.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.stylefeng.guns.base.pojo.page.LayuiPageFactory;
import cn.stylefeng.guns.base.pojo.page.LayuiPageInfo;
import cn.stylefeng.guns.core.util.DateUtil;
import cn.stylefeng.guns.core.util.DateUtil2;
import cn.stylefeng.guns.modular.agv.entity.*;
import cn.stylefeng.guns.modular.agv.mapper.AgvStoragePositionMapper;
import cn.stylefeng.guns.modular.agv.mapper.AgvStorageTaskDetailMapper;
import cn.stylefeng.guns.modular.agv.mapper.AgvStorageTaskMapper;
import cn.stylefeng.guns.modular.agv.model.params.*;
import cn.stylefeng.guns.modular.agv.model.result.AgvStoragePositionResult;
import cn.stylefeng.guns.modular.agv.model.result.AgvStorageTaskDetailResult;
import cn.stylefeng.guns.modular.agv.model.result.AgvStorageTaskResult;
import cn.stylefeng.guns.modular.agv.service.*;
import cn.stylefeng.guns.modular.agv.util.*;
import cn.stylefeng.guns.modular.basic.entity.BasicCustomer;
import cn.stylefeng.guns.modular.basic.entity.BasicOperate;
import cn.stylefeng.guns.modular.basic.entity.BasicPosition;
import cn.stylefeng.guns.modular.basic.entity.BasicPutgoods;
import cn.stylefeng.guns.modular.basic.model.params.BasicAddressParam;
import cn.stylefeng.guns.modular.basic.model.result.BasicAddressResult;
import cn.stylefeng.guns.modular.basic.service.*;
import cn.stylefeng.guns.modular.hx.basic.model.params.HxBasicGoodsParam;
import cn.stylefeng.guns.modular.hx.basic.model.result.HxBasicGoodsResult;
import cn.stylefeng.guns.modular.hx.basic.service.HxBasicGoodsService;
import cn.stylefeng.guns.modular.hx.dps.entity.DpsZcServer;
import cn.stylefeng.guns.modular.hx.order.utils.JdbcUtls;
import cn.stylefeng.guns.modular.hx.order.utils.MssqlUtils;
import cn.stylefeng.guns.modular.hx.storage.entity.HxStorageOut;
import cn.stylefeng.guns.modular.hx.storage.entity.HxStorageOutDetailed;
import cn.stylefeng.guns.modular.hx.storage.entity.HxStorageStock;
import cn.stylefeng.guns.modular.hx.storage.mapper.HxStorageOutDetailedMapper;
import cn.stylefeng.guns.modular.hx.storage.mapper.HxStorageOutMapper;
import cn.stylefeng.guns.modular.hx.storage.model.params.HxCollectionLocationParam;
import cn.stylefeng.guns.modular.hx.storage.model.params.HxStorageOutDetailedParam;
import cn.stylefeng.guns.modular.hx.storage.model.params.HxStorageOutParam;
import cn.stylefeng.guns.modular.hx.storage.model.params.HxStorageStockParam;
import cn.stylefeng.guns.modular.hx.storage.model.result.*;
import cn.stylefeng.guns.modular.hx.storage.model.vo.DpsMidOrdersCRVo;
import cn.stylefeng.guns.modular.hx.storage.model.vo.DpsMidOrdersCVo;
import cn.stylefeng.guns.modular.hx.storage.model.vo.SqlServerConnVo;
import cn.stylefeng.guns.modular.hx.storage.service.HxCollectionLocationService;
import cn.stylefeng.guns.modular.hx.storage.service.HxStorageOutDetailedService;
import cn.stylefeng.guns.modular.hx.storage.service.HxStorageOutService;
import cn.stylefeng.guns.modular.hx.storage.service.HxStorageStockService;
import cn.stylefeng.guns.modular.order.model.params.OrderTransportDetailedParam;
import cn.stylefeng.guns.modular.order.model.params.OrderTransportParam;
import cn.stylefeng.guns.modular.order.model.result.OrderTransportResult;
import cn.stylefeng.guns.modular.order.service.OrderTransportDetailedService;
import cn.stylefeng.guns.modular.order.service.OrderTransportService;
import cn.stylefeng.guns.modular.rest.agv.vo.StorageOutCntOby;
import cn.stylefeng.guns.modular.rest.agv.vo.SueTaskIby;
import cn.stylefeng.guns.modular.rest.aop.UserAop;
import cn.stylefeng.guns.sys.modular.system.entity.Dept;
import cn.stylefeng.guns.sys.modular.system.entity.User;
import cn.stylefeng.guns.sys.modular.system.service.DeptService;
import cn.stylefeng.guns.sys.modular.system.service.UserService;
import cn.stylefeng.roses.core.reqres.response.ResponseData;
import cn.stylefeng.roses.core.util.ToolUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mchange.lang.LongUtils;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.annotation.Resource;
import java.io.Serializable;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 拣货单表 服务实现类
 * </p>
 *
 * @author zhucx
 * @since 2023-09-05
 */
@Service
public class HxStorageOutServiceImpl extends ServiceImpl<HxStorageOutMapper, HxStorageOut> implements HxStorageOutService {

    @Resource
    private HxStorageOutDetailedMapper hxStorageOutDetailedMapper;

    @Autowired
    private UserAop userAop;

    @Autowired
    private BasicCustomerService basicCustomerService;

    @Autowired
    private HxCollectionLocationService hxCollectionLocationService;

    @Autowired
    private HxStorageOutDetailedService hxStorageOutDetailedService;

    @Autowired
    private HxStorageStockService hxStorageStockService;

    @Autowired
    private BasicPositionService basicPositionService;

    @Autowired
    private OrderTransportService orderTransportService;

    @Autowired
    private BasicAddressService basicAddressService;

    @Autowired
    private BasicPutgoodsService basicPutgoodsService;

    @Resource
    private DeptService deptService;

    @Resource
    private OrderTransportDetailedService orderTransportDetailedService;

    @Autowired
    private BasicOperateService basicOperateService;

    @Autowired
    private HxBasicGoodsService goodsService;

    @Resource
    private AgvStorageTaskService agvStorageTaskService;

    @Autowired
    private UserService userService;

    @Resource
    private HxStorageOutService hxStorageOutService;

    @Resource
    private AgvStorageTaskMapper agvStorageTaskMapper;

    @Resource
    private AgvStorageTaskDetailService agvStorageTaskDetailService;

    @Resource
    private AgvStorageTaskDetailMapper agvStorageTaskDetailMapper;

    @Resource
    private AgvStoragePositionService agvStoragePositionService;

    @Resource
    private AgvStoragePositionMapper agvStoragePositionMapper;

    @Autowired
    private AgvStorageTaskListService agvStorageTaskListService;

    @Autowired
    private AgvAreaQuotaService agvAreaQuotaService;

    @Override
    public void add(HxStorageOutParam param) {
        HxStorageOut entity = getEntity(param);
        this.save(entity);
    }

    @Override
    public void delete(HxStorageOutParam param) {
        this.removeById(getKey(param));
    }

    @Override
    public void update(HxStorageOutParam param) {
        HxStorageOut oldEntity = getOldEntity(param);
        HxStorageOut newEntity = getEntity(param);
        ToolUtil.copyProperties(newEntity, oldEntity);
        this.updateById(newEntity);
    }

    @Override
    public HxStorageOutResult findBySpec(HxStorageOutParam param) {
        return this.baseMapper.findBySpec(param);
    }

    @Override
    public List<HxStorageOutResult> findListBySpec(HxStorageOutParam param) {
        return this.baseMapper.customList(param);
    }

    @Override
    public List<HxStorageOutResult> query(HxStorageOutParam param) {
        return this.baseMapper.query(param);
    }

    @Override
    public List<HxStorageOutResult> queryByGetUnitId(Long getUnitId) {
        return this.baseMapper.queryByGetUnitId(getUnitId);
    }

    @Override
    public LayuiPageInfo findPageBySpec(HxStorageOutParam param, String condition, Long operateId) {
        Page pageContext = getPageContext();
        IPage page = this.baseMapper.customPageList(pageContext, param, condition, operateId);
        return LayuiPageFactory.createPageInfo(page);
    }

    // 拣货人员信息统计
    @Override
    public LayuiPageInfo findstorageuser(HxStorageOutParam hxStorageOutParam, String condition) {


        Page pageContext = getPageContext();
        IPage printStorageuser = this.baseMapper.getPrintStorageuser(pageContext, hxStorageOutParam, condition);
        List<HxStorageOutResult> records = printStorageuser.getRecords();

        for (HxStorageOutResult item : records) {
            BigDecimal storageNumbers = new BigDecimal(item.getStorageNumbers()).setScale(2, BigDecimal.ROUND_HALF_UP);
            Integer uniqueHours = item.getUniqueHours();
            if (uniqueHours == null || uniqueHours == 0) {
                item.setAverageStorageNumber(new BigDecimal(0));
            } else {
                BigDecimal bigUniqueHours = new BigDecimal(uniqueHours).setScale(2, BigDecimal.ROUND_HALF_UP);
                BigDecimal divide = storageNumbers.divide(bigUniqueHours, 2, BigDecimal.ROUND_HALF_UP);
                item.setHourlyWorkload(divide);
            }
        }
        printStorageuser.setRecords(records);
        return LayuiPageFactory.createPageInfo(printStorageuser);
    }

    // 出库质检信息统计
    @Override
    public LayuiPageInfo findqualityuser(HxStorageOutParam hxStorageOutParam, String condition) {
        Page pageContext = getPageContext();
        IPage printQualityuser = this.baseMapper.getPrintQualityuser(pageContext, hxStorageOutParam, condition);
        return LayuiPageFactory.createPageInfo(printQualityuser);
    }


    private Serializable getKey(HxStorageOutParam param) {
        return param.getId();
    }

    private Page getPageContext() {
        return LayuiPageFactory.defaultPage();
    }

    private HxStorageOut getOldEntity(HxStorageOutParam param) {
        return this.getById(getKey(param));
    }

    private HxStorageOut getEntity(HxStorageOutParam param) {
        HxStorageOut entity = new HxStorageOut();
        ToolUtil.copyProperties(param, entity);
        return entity;
    }

    @Override
    public HxStorageOut findByThelastone() {
        return this.baseMapper.findByThelastone();
    }

    @Override
    public boolean saveBatchList(List<HxStorageOutParam> list) {
        return this.baseMapper.saveBatchList(list);
    }

    @Override
    public LayuiPageInfo findAppDailingquPageBySpec(HxStorageOutParam param) {
        Page pageContext = getPageContext();
        IPage page = this.baseMapper.findAppDailingquPageBySpec(pageContext, param);
        return LayuiPageFactory.createPageInfo(page);
    }

    @Override
    public List<HxStorageOutResult> findAppYilingquBySpec(HxStorageOutParam param) {
        return this.baseMapper.findAppYilingquBySpec(param);
    }

    @Override
    public HxStorageOutResult findSumBySpec(HxStorageOutParam param) {
        return this.baseMapper.findSumBySpec(param);
    }

    @Override
    public HxStorageOutResult lockBySpec(HxStorageOutParam param) {
        return this.baseMapper.lockBySpec(param);
    }

    @Override
    @Transactional(rollbackFor = Exception.class, timeout = 60)
    public ResponseData completeStorage(HxStorageOutDetailedParam hxStorageOutDetailedParam, User user) {
        String stockPort = "";
        HxStorageOutParam storageOutParam = new HxStorageOutParam();
        storageOutParam.setStorageNumber(hxStorageOutDetailedParam.getStorageNumber());
        HxStorageOutResult storageOutResult = this.findSumBySpec(storageOutParam);

        BasicPutgoods basicPutgoods = this.basicPutgoodsService.getById(storageOutResult.getGetUnitId());

        if (storageOutResult == null || !storageOutResult.getStorageState().equals("拣货中")) {
            return ResponseData.error("拣货任务不存在或已拣货");
        }
        if (ToolUtil.isEmpty(storageOutResult.getStockPort())) {
            return ResponseData.error("未分配集货口");
        }
        //如果是拆托，把已经完成拣货的新创建一个单及明细
        if (ToolUtil.isNotEmpty(hxStorageOutDetailedParam.getIsCt()) && "1".equals(hxStorageOutDetailedParam.getIsCt())) {
            //根据拣货单号，获取最大的拣货单号
            HxStorageOut one = this.lambdaQuery()
                    .likeRight(HxStorageOut::getStorageNumber, hxStorageOutDetailedParam.getStorageNumber())
                    .orderByDesc(HxStorageOut::getStorageNumber)
                    .one();
            //新增拣货单
            HxStorageOutParam add = new HxStorageOutParam();
            ToolUtil.copyProperties(one, add);

            String storageNumber = one.getStorageNumber();
            int idex = storageNumber.lastIndexOf("-");
            if (idex > 0) {
                String str1 = storageNumber.substring(0, idex);
                String str2 = storageNumber.substring(idex + 1);
                try {
                    int icnt = Integer.parseInt(str2);
                    icnt++;
                    storageNumber = str1 + "-" + icnt;
                    add.setTrayNumber(one.getTrayNumber() + "-" + icnt);
                } catch (Exception e) {
                    storageNumber = storageNumber + "-1";
                    add.setTrayNumber(one.getTrayNumber() + "-1");
                    e.printStackTrace();
                }
            } else {
                storageNumber = storageNumber + "-1";
                add.setTrayNumber(one.getTrayNumber() + "-1");
            }

            add.setId(null);
            add.setStorageNumber(storageNumber);
            this.add(add);
            //修改明细对应的拣货单号
            hxStorageOutDetailedService.lambdaUpdate()
                    .eq(HxStorageOutDetailed::getStorageNumber, hxStorageOutDetailedParam.getStorageNumber())
                    .apply("num = real_num")
                    .set(HxStorageOutDetailed::getStorageNumber, storageNumber)
                    .update();
            //新增明细
            hxStorageOutDetailedService.addByStorageNumber(hxStorageOutDetailedParam.getStorageNumber(), storageNumber);
            //修改原拣货单数量
            List<HxStorageOutDetailedResult> hxStorageOutDetailedResults = hxStorageOutDetailedService.selectGoodSNumByStorageNumber(hxStorageOutDetailedParam.getStorageNumber());
            for (HxStorageOutDetailedResult obj : hxStorageOutDetailedResults) {
                String sql = "num = " + obj.getNum() + ",real_num=0,out_weight=goods_weight*" + obj.getNum() + ",out_volume=goods_volume*" + obj.getNum() + ",jiben_num=rate*" + obj.getNum() + ",out_money=goods_price*" + obj.getNum();
                hxStorageOutDetailedService.lambdaUpdate()
                        .eq(HxStorageOutDetailed::getId, obj.getId())
                        .setSql(sql)
                        .update();
            }
            //重新完成拣货
            storageOutParam = new HxStorageOutParam();
            storageOutParam.setStorageNumber(storageNumber);
            storageOutResult = this.findSumBySpec(storageOutParam);
            hxStorageOutDetailedParam.setStorageNumber(storageNumber);
        }

        if (ToolUtil.isNotEmpty(hxStorageOutDetailedParam.getSumNum())) {
            BigDecimal sumNum = new BigDecimal(hxStorageOutDetailedParam.getSumNum());
            BigDecimal realNumd = new BigDecimal(storageOutResult.getRealNum());
            if (sumNum.compareTo(realNumd) != 0) {
                return ResponseData.error("输入总数量与实拣不一致！");
            }
        }


        stockPort = storageOutResult.getStockPort();

        BasicCustomer basicCustomer = basicCustomerService.getById(storageOutResult.getCustomerId());

        if (ToolUtil.isNotEmpty(basicCustomer.getNeedCheck()) && basicCustomer.getNeedCheck().equals("1")) {//如果质检
            storageOutParam.setStorageState("待复核");
            storageOutParam.setId(storageOutResult.getId());
            storageOutParam.setStorageCompleteTime(new Date());
            this.update(storageOutParam);
        } else {
            storageOutParam.setStorageState("已完成");
            storageOutParam.setId(storageOutResult.getId());
            storageOutParam.setStorageCompleteTime(new Date());
            this.update(storageOutParam);
        }

        HxCollectionLocationParam hxCollectionLocationParam = new HxCollectionLocationParam();
        hxCollectionLocationParam.setStatus("已占用");
        hxCollectionLocationParam.setTrayNumber(storageOutResult.getTrayNumber());
        hxCollectionLocationParam.setStockPort(stockPort);
        hxCollectionLocationParam.setDeptId(user.getDeptId());
        hxCollectionLocationParam.setOperateId(user.getOperateId());
        hxCollectionLocationService.deliveryTray(hxCollectionLocationParam);

        if (ToolUtil.isEmpty(basicCustomer.getBoxPickMode()) || basicCustomer.getBoxPickMode().equals("0")) {
            if (ToolUtil.isEmpty(storageOutResult.getScattered())) {
                hxStorageOutDetailedService.updaterealNumBySpec(hxStorageOutDetailedParam);//更新实拣数量 = 应拣数量(应急可以取消整箱区扫码拣选)
            }
        }
        //扣减库存
        HxStorageOutDetailedParam hxStorageOutDetailedParamf = new HxStorageOutDetailedParam();
        hxStorageOutDetailedParamf.setStorageNumber(hxStorageOutDetailedParam.getStorageNumber());
        List<HxStorageOutDetailedResult> dlist = hxStorageOutDetailedService.findListBySpec(hxStorageOutDetailedParamf);
        BigDecimal as = new BigDecimal("0");
        BigDecimal shi = new BigDecimal("10");
        List<HxStorageStock> sadd = new ArrayList<HxStorageStock>();
        for (HxStorageOutDetailedResult d : dlist) {
            HxStorageStockParam subHxStorageStockParam = new HxStorageStockParam();
            if (d.getStockId() != null) {
                subHxStorageStockParam.setId(Integer.parseInt(d.getStockId().toString()));
            }
            if (ToolUtil.isNotEmpty(d.getStockId()) && "是".equals(storageOutResult.getPalletStorageAreaFlag())) {

            } else {
                subHxStorageStockParam.setStockState("正常");
                subHxStorageStockParam.setWarehouseId(storageOutResult.getSetWarehouseId());
                subHxStorageStockParam.setPositionId(d.getPositionId());
                subHxStorageStockParam.setPositionType("拣货位");
                subHxStorageStockParam.setGoodsId(d.getGoodsId());
            }
            List<HxStorageStockResult> subs = hxStorageStockService.findsubListBySpec(subHxStorageStockParam);
            BigDecimal rate = new BigDecimal(d.getRate());//出库换算率
            if (ToolUtil.isEmpty(d.getRealNum())) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); //手动回滚
                return ResponseData.error(d.getGoodsName() + ",未拣货!");
            }
            BigDecimal num = new BigDecimal(d.getNum());//数量
            BigDecimal realNum = new BigDecimal(d.getRealNum());//实拣数量
            if (num.compareTo(realNum) != 0) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); //手动回滚
                return ResponseData.error(d.getGoodsName() + ",应拣与实拣不一致!");
            }
            //实拣基本数量
            BigDecimal realNumJiben = realNum.multiply(new BigDecimal(d.getRate()));
            for (HxStorageStockResult obj : subs) {
                BigDecimal _kcRate = new BigDecimal(obj.getKcRate());
                //修改拣货明细计量
                if (ToolUtil.isEmpty(d.getDetailedDate())) {
                    d.setDetailedDate(obj.getDetailedDate());
                    d.setDaoqiDate(obj.getExpirationDate());
                    HxStorageOutDetailedParam sdp = new HxStorageOutDetailedParam();
                    sdp.setId(d.getId());
                    sdp.setDetailedDate(obj.getDetailedDate());
                    sdp.setDaoqiDate(obj.getExpirationDate());
                    hxStorageOutDetailedService.update(sdp);
                }
                //库存数量大于拣货数量 库存计量需要拆开
                if (obj.getJibenNum().compareTo(realNumJiben) == 1) {
                    //基本单位对应的体积重量
                    BigDecimal goodsVolume = new BigDecimal(obj.getStockVolume()).divide(obj.getJibenNum(), 10, BigDecimal.ROUND_HALF_DOWN);
                    BigDecimal goodsWeight = new BigDecimal(obj.getStockWeight()).divide(obj.getJibenNum(), 10, BigDecimal.ROUND_HALF_DOWN);
                    ;
                    BigDecimal goodsPrice = new BigDecimal(obj.getStockMoney()).divide(obj.getJibenNum(), 10, BigDecimal.ROUND_HALF_DOWN);
                    ;
                    //剩余库存
                    BigDecimal sykc = obj.getJibenNum().subtract(realNumJiben);
                    //修改扣除后的库存计量
                    HxStorageStockParam updateHxStorageStockParam = new HxStorageStockParam();
                    updateHxStorageStockParam.setId(obj.getId());
                    updateHxStorageStockParam.setStockVolume(sykc.multiply(goodsVolume).setScale(4, BigDecimal.ROUND_HALF_DOWN).toString());
                    updateHxStorageStockParam.setStockWeight(sykc.multiply(goodsWeight).setScale(3, BigDecimal.ROUND_HALF_DOWN).toString());
                    updateHxStorageStockParam.setStockMoney(sykc.multiply(goodsPrice).setScale(3, BigDecimal.ROUND_HALF_DOWN).toString());
                    updateHxStorageStockParam.setKcNum(String.valueOf(sykc.divide(_kcRate, 3, BigDecimal.ROUND_HALF_DOWN)));
                    updateHxStorageStockParam.setJibenNum(sykc);
                    hxStorageStockService.update(updateHxStorageStockParam);
                    //添加集货区库存
                    HxStorageStock updateHxStorageStockParamadd = new HxStorageStock();
                    ToolUtil.copyProperties(obj, updateHxStorageStockParamadd);
                    updateHxStorageStockParamadd.setId(null);
                    updateHxStorageStockParamadd.setStorageNumber(storageOutResult.getStorageNumber());
                    updateHxStorageStockParamadd.setStockState("集货");
                    updateHxStorageStockParamadd.setAreaId(null);
                    updateHxStorageStockParamadd.setAreaNumber(null);
                    updateHxStorageStockParamadd.setAreaName("集货区");
//                        updateHxStorageStockParamadd.setPositionId(null);
                    updateHxStorageStockParamadd.setPositionType("集货位");
                    updateHxStorageStockParamadd.setPositionNumber(storageOutResult.getStockPort());
                    updateHxStorageStockParamadd.setTrayNumber(storageOutResult.getTrayNumber());
                    updateHxStorageStockParamadd.setStockVolume(realNumJiben.multiply(goodsVolume).setScale(4, BigDecimal.ROUND_HALF_DOWN).toString());
                    updateHxStorageStockParamadd.setStockWeight(realNumJiben.multiply(goodsWeight).setScale(3, BigDecimal.ROUND_HALF_DOWN).toString());
                    updateHxStorageStockParamadd.setStockMoney(realNumJiben.multiply(goodsPrice).setScale(3, BigDecimal.ROUND_HALF_DOWN).toString());
                    updateHxStorageStockParamadd.setKcNum(String.valueOf(realNumJiben.divide(_kcRate, 3, BigDecimal.ROUND_HALF_DOWN)));
                    updateHxStorageStockParamadd.setJibenNum(realNumJiben);
                    sadd.add(updateHxStorageStockParamadd);
                    realNumJiben = new BigDecimal(0);
                } else {
                    hxStorageStockService.lambdaUpdate()
                            .eq(HxStorageStock::getId, obj.getId())
                            .set(HxStorageStock::getStorageNumber, storageOutResult.getStorageNumber())
                            .set(HxStorageStock::getStockState, "集货")
                            .set(HxStorageStock::getAreaId, null)
                            .set(HxStorageStock::getAreaNumber, null)
                            .set(HxStorageStock::getAreaName, "集货区")
//                                .set(HxStorageStock::getPositionId, null)
                            .set(HxStorageStock::getPositionType, "集货位")
                            .set(HxStorageStock::getPositionNumber, storageOutResult.getStockPort())
                            .set(HxStorageStock::getTrayNumber, storageOutResult.getTrayNumber())
                            .update();
                    realNumJiben = realNumJiben.subtract(obj.getJibenNum());
                }
                //拣货数量为0时，退出循环
                if (realNumJiben.compareTo(as) == 0) {
                    break;
                }
            }
            //库存循环完，还有未扣库存，说明货物不足
            if (realNumJiben.compareTo(as) == 1) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); //手动回滚
                return ResponseData.error(d.getGoodsName() + ",拣货位货物不足!");
            }
        }
        if (sadd.size() > 0) {
            hxStorageStockService.saveBatch(sadd);
        }

        if (ToolUtil.isEmpty(basicCustomer.getNeedCheck()) || basicCustomer.getNeedCheck().equals("2")) {//如果不质检
            //新增货运订单
            if (ToolUtil.isNotEmpty(basicCustomer.getGenerateTms())) {
                if (basicCustomer.getGenerateTms().equals("1")) {
                    OrderTransportParam ch = new OrderTransportParam();
                    ch.setCustomerOrder(storageOutResult.getTrayNumber() + "_" + storageOutResult.getStorageNumber());
                    OrderTransportResult chr = orderTransportService.checkyouwu(ch);
                    if (chr == null) {
                        List<OrderTransportDetailedParam> transportdList = new ArrayList<OrderTransportDetailedParam>();//批量保存的 货运订单list
                        BasicOperate basicOperate = basicOperateService.getById(basicCustomer.getCustomerOperateId());
                        String trayCode = getOperateIdOrderPrefix(user);
                        String name = "零脉";

                        OrderTransportParam addp = new OrderTransportParam();
                        addp.setOperateId(Long.parseLong(basicCustomer.getCustomerOperateId().toString()));//分公司id
                        addp.setOperateName(basicOperate.getOperateName());//公司名称
                        addp.setCustomerOrder(storageOutResult.getTrayNumber() + "_" + storageOutResult.getStorageNumber());
                        addp.setTransportNumber(trayCode + "HY" + cn.stylefeng.guns.core.util.DateUtil.getDatesBch() + DateUtil.getRandomNumber());
                        addp.setOrderNumber(storageOutResult.getStorageNumber());
                        addp.setDemolition(storageOutResult.getScattered());
                        addp.setLmOrderType(storageOutResult.getOrderType());
                        addp.setLmAssociationOrder(storageOutResult.getAssociationOrder());
                        addp.setOrderSource("零脉");
                        if (ToolUtil.isNotEmpty(storageOutResult.getPieceNumber())) {
                            addp.setPieceNumber(storageOutResult.getPieceNumber());
                        } else {
                            if (ToolUtil.isNotEmpty(storageOutResult.getScattered())) {
                                BigDecimal realNum = new BigDecimal(storageOutResult.getRealNum());
                                if (realNum.compareTo(as) == 1) {
                                    BigDecimal pieceNumberbig = realNum.divide(shi, 3, BigDecimal.ROUND_HALF_DOWN);
                                    addp.setPieceNumber(pieceNumberbig + "");
                                } else {
                                    addp.setPieceNumber("0");
                                }
                            } else {
                                addp.setPieceNumber("0");
                            }
                        }
                        addp.setCustomerId(Long.parseLong(basicCustomer.getId().toString()));//客户id
                        addp.setCustomerName(basicCustomer.getCustomerName());//客户名称
                        addp.setUndertime(DateUtil2.getDateS());//下单时间
                        addp.setSetMentiontime(storageOutResult.getPeisongTime());//发货日期

                        addp.setXlbSetUnitId(storageOutResult.getXlbSetUnitId());
                        addp.setSetUnit(storageOutResult.getSetUnit());//装货单位
                        addp.setSetUnitId(storageOutResult.getSetUnitId());//装货单位id
                        addp.setXlbSetWarehouse(storageOutResult.getSetWarehouse());
                        addp.setXlbSetWarehouseId(storageOutResult.getXlbSetWarehouseId());
                        addp.setXlbClientId(storageOutResult.getXlbClientId());
                        addp.setGetUnit(storageOutResult.getGetUnit());
                        addp.setGetUnitId(storageOutResult.getGetUnitId());
                        addp.setStockPort(storageOutResult.getStockPort());//备货口

                        toDealWith4(addp);//处理单位和地址

                        addp.setDeptId(user.getDeptId());
                        addp.setDeliverId(user.getDeliverId());
                        addp.setCreateName(name);
                        addp.setCreateTime(new Date());
                        addp.setGoodsNum(storageOutResult.getGoodsNum());

                        addp.setTooNum("0");
                        addp.setTooVolume("0");
                        addp.setTstate("待调");
                        BigDecimal TotalNum = new BigDecimal("0");//货物单总数
                        BigDecimal TotalVolume = new BigDecimal("0");//货物单总体积
                        //货品信息
//                            HxBasicGoodsParam q = new HxBasicGoodsParam();
//                            q.setDeptId(storageOutResult.getDeptId());
//                            List<HxBasicGoodsResult> hxBasicGoodsResults = goodsService.findlistAllBySpec(q, null, Long.valueOf(basicCustomer.getCustomerOperateId()));
//                            Map<String,HxBasicGoodsResult> hxBasicGoodsMap = new HashedMap();
//                            for(HxBasicGoodsResult obj : hxBasicGoodsResults){
//                                hxBasicGoodsMap.put(obj.getId().toString(),obj);
//                            }

                        hxStorageOutDetailedParamf = new HxStorageOutDetailedParam();
                        hxStorageOutDetailedParamf.setStorageNumber(hxStorageOutDetailedParam.getStorageNumber());
                        List<HxStorageOutDetailedResult> hxStorageOutDetaileds = hxStorageOutDetailedService.findListBySpec(hxStorageOutDetailedParamf);
                        Map<String, HxStorageOutDetailedResult> hxBasicGoodsMap = new HashedMap();
                        for (HxStorageOutDetailedResult obj : hxStorageOutDetaileds) {
                            hxBasicGoodsMap.put(obj.getGoodsId().toString(), obj);
                        }
                        //根据拣货单号获取库存列表
                        HxStorageStockParam hxStorageStockParam = new HxStorageStockParam();
                        hxStorageStockParam.setStorageNumber(storageOutResult.getStorageNumber());
                        hxStorageStockParam.setWarehouseId(storageOutResult.getSetWarehouseId());
                        List<HxStorageStockResult> hxStorageStockStorageNumbers = hxStorageStockService.findListByStorageNumber1(hxStorageStockParam);
                        //库位信息
                        List<BasicPosition> basicPositions = basicPositionService.lambdaQuery()
                                .eq(BasicPosition::getWarehouseId, storageOutResult.getSetWarehouseId())
                                .eq(BasicPosition::getPositionType, "拣货位")
                                .list();
                        Map<String, BasicPosition> basicPositionMap = new HashedMap();
                        for (BasicPosition obj : basicPositions) {
                            basicPositionMap.put(obj.getId().toString(), obj);
                        }

                        for (HxStorageStockResult obj : hxStorageStockStorageNumbers) {
                            //新增货运明细
                            OrderTransportDetailedParam outTranDetailed = new OrderTransportDetailedParam();
                            outTranDetailed.setTransportNumber(addp.getTransportNumber());

                            if (ToolUtil.isNotEmpty(obj.getPositionId()) && basicPositionMap.get(obj.getPositionId().toString()) != null) {
                                outTranDetailed.setXlbPositionId(basicPositionMap.get(obj.getPositionId().toString()).getPositionXlbId());
                                outTranDetailed.setPositionNumber(basicPositionMap.get(obj.getPositionId().toString()).getPositionNumber());
                            }
                            outTranDetailed.setPositionId(obj.getPositionId());


                            outTranDetailed.setGoodsVolume(obj.getGoodsVolume());
                            outTranDetailed.setTransportPutvolume(obj.getStockVolume());
                            outTranDetailed.setGoodsWeight(obj.getGoodsWeight());
                            outTranDetailed.setTransportWeight(obj.getStockWeight());
                            outTranDetailed.setUnitprice(hxBasicGoodsMap.get(obj.getGoodsId().toString()).getGoodsPrice());
                            //金额=单价/rate*基本数量
                            if (ToolUtil.isNotEmpty(hxBasicGoodsMap.get(obj.getGoodsId().toString()).getGoodsPrice()) && ToolUtil.isNotEmpty(hxBasicGoodsMap.get(obj.getGoodsId().toString()).getRate())) {
                                BigDecimal transportMoney = obj.getJibenNum().multiply(new BigDecimal(hxBasicGoodsMap.get(obj.getGoodsId().toString()).getGoodsPrice())).divide(new BigDecimal(hxBasicGoodsMap.get(obj.getGoodsId().toString()).getRate()), 3, BigDecimal.ROUND_HALF_DOWN).setScale(3, BigDecimal.ROUND_HALF_DOWN);
                                outTranDetailed.setTransportMoney(transportMoney.toString());
                            }
//                                outTranDetailed.setTransportMoney(obj.getStockMoney());

                            outTranDetailed.setXlbGoodsId(hxBasicGoodsMap.get(obj.getGoodsId().toString()).getXlbGoodsId());
                            outTranDetailed.setGoodId(obj.getGoodsId());
                            outTranDetailed.setGoodsName(obj.getGoodsName());
                            outTranDetailed.setGoodsNumber(obj.getGoodsNumber());
                            outTranDetailed.setGoodsPcode69(obj.getGoodsPcode69());
                            outTranDetailed.setGoodsUnit(obj.getKcUnit());
                            outTranDetailed.setGoodsSpecs(obj.getGoodsSpecs());

                            outTranDetailed.setJibenUnit(obj.getJibenUnit());
                            outTranDetailed.setJibenNum(String.valueOf(obj.getJibenNum()));
                            outTranDetailed.setBalenum(obj.getKcNum());
                            outTranDetailed.setNum(obj.getKcNum());
                            outTranDetailed.setRate(obj.getKcRate());

                            outTranDetailed.setDetailedDate(obj.getDetailedDate());
                            outTranDetailed.setDaoqiDate(obj.getExpirationDate());

                            outTranDetailed.setNotnum(outTranDetailed.getNum());
                            outTranDetailed.setNotvolume(outTranDetailed.getTransportPutvolume());
                            BigDecimal num = new BigDecimal(outTranDetailed.getNum());
                            if (num.compareTo(as) == 1) {
                                transportdList.add(outTranDetailed);
                            } else {
                                continue;
                            }

                            BigDecimal transportPutvolume = new BigDecimal(outTranDetailed.getTransportPutvolume());
                            BigDecimal nTotalNum = TotalNum.add(num);
                            TotalNum = nTotalNum;
                            BigDecimal nTotalVolume = TotalVolume.add(transportPutvolume);
                            TotalVolume = nTotalVolume;
                        }
                        addp.setTotalNum(TotalNum.setScale(3, BigDecimal.ROUND_HALF_DOWN).toString());
                        addp.setTotalVolume(TotalVolume.setScale(4, BigDecimal.ROUND_HALF_DOWN).toString());
                        if (TotalNum.compareTo(as) == 1) {
                            orderTransportService.add(addp);
                            if (transportdList.size() > 0) {
                                this.orderTransportDetailedService.saveBatchList(transportdList);
                            }
                        }
                    }
                }
            }
        }
        StringBuffer returnStr = new StringBuffer();
        returnStr.append("备货口：").append(stockPort);
        if(ToolUtil.isNotEmpty(basicPutgoods) && ToolUtil.isNotEmpty(basicPutgoods.getUnitNumber())){
            returnStr.append("</br>客户编号：").append(basicPutgoods.getUnitNumber());
        }
        return ResponseData.success(returnStr.toString());
    }


    private void toDealWith4(OrderTransportParam addp) {
        //查询装货地点 是否存在
        BasicAddressParam bap = new BasicAddressParam();
        bap.setPutgoodsId(addp.getSetUnitId());//单位id
        BasicAddressResult bar = basicAddressService.findBySpec(bap);//通过单位id 地址 查询
        if (bar != null) {
            addp.setSetLocation(bar.getAddress());//装货地址
            addp.setSetLocationId(Long.parseLong(bar.getId().toString()));//装货地址id
            addp.setSetPeople(bar.getContacts());//联系人
            addp.setSetTel(bar.getTel());//联系电话
        } else {//如果没有地址  装货地址为 单位名称
            bap.setAddress(addp.getSetUnit());//地点 为单位名称
            bap.setPutgoodsName(addp.getSetUnit());//单位名称
            bap.setLongitude("0");
            bap.setLatitude("0");
            bap.setSwitchWl("1");
            bap.setSwitchBj("1500");//提货围栏半径 默认100米
            bap.setSwitchBj2("2000");//收货围栏半径 默认100米
            basicAddressService.add(bap);
            BasicAddressParam bap2 = new BasicAddressParam();
            bap2.setPutgoodsId(addp.getSetUnitId());
            bar = basicAddressService.findBySpec(bap2);
            addp.setSetLocation(bar.getAddress());//装货地址
            addp.setSetLocationId(Long.parseLong(bar.getId().toString()));//装货地址id
        }
        //查询卸货地点 是否存在
        BasicAddressParam bap3 = new BasicAddressParam();
        bap3.setPutgoodsId(addp.getGetUnitId());//单位id
        BasicAddressResult bar2 = basicAddressService.findBySpec(bap3);//通过单位id 地址 查询
        if (bar2 != null) {
            addp.setGetLocationId(Long.parseLong(bar2.getId().toString()));//卸货地址id
            addp.setGetLocation(bar2.getAddress());//卸货地址
            addp.setGetPeople(bar2.getContacts());//联系人
            addp.setGetTel(bar2.getTel());//联系电话
            addp.setKilometer(bar2.getKilometer());
            addp.setLineId(bar2.getLineId());
            addp.setLineName(bar2.getLineName());
        } else {//如果没有地址 ，  卸货地址为 单位名称
            bap3.setAddress(addp.getGetUnit());//地点 为单位名称
            bap3.setPutgoodsName(addp.getGetUnit());//单位名称
            bap3.setLongitude("0");
            bap3.setLatitude("0");
            bap3.setSwitchWl("1");
            bap3.setSwitchBj("1500");//提货围栏半径 默认100米
            bap3.setSwitchBj2("2000");//收货围栏半径 默认100米
            basicAddressService.add(bap3);
            BasicAddressParam bap4 = new BasicAddressParam();
            bap4.setPutgoodsId(addp.getGetUnitId());
            bap4.setAddress(addp.getGetUnit());
            bar2 = basicAddressService.findBySpec(bap4);
            addp.setGetLocation(bar2.getAddress());//卸货地址
            addp.setGetLocationId(Long.parseLong(bar2.getId().toString()));//卸货地址id
        }
    }

    /**
     * 获取所属项目单号前缀
     *
     * @param user
     * @return
     */
    public String getOperateIdOrderPrefix(User user) {
        if (user.getOperateId() != null) {
            Dept dept = new Dept();
            dept.setOperateId(user.getOperateId());
            Dept resdept = deptService.findBySpec(dept);
            if (resdept != null) {
                if (ToolUtil.isNotEmpty(resdept.getOrderPrefix())) {
                    return resdept.getOrderPrefix();
                } else {
                    return user.getAccount().substring(0, 3);
                }
            } else {
                return null;
            }
        } else {
            return null;
        }
    }


    @Override
    public LayuiPageInfo findAppDailingquzhijianPageBySpec(HxStorageOutParam hxStorageOutParam) {
        Page pageContext = getPageContext();
        IPage page = this.baseMapper.findAppDailingquzhijianPageBySpec(pageContext, hxStorageOutParam);
        return LayuiPageFactory.createPageInfo(page);
    }

    @Override
    public List<HxStorageOutResult> findAppYilingquzhijianBySpec(HxStorageOutParam hxStorageOutParam) {
        return this.baseMapper.appfindyilingquzhijian(hxStorageOutParam);
    }

    @Override
    public HxStorageOutResult getPrintStorageOut(HxStorageOutParam hxStorageOutParam) {
        return this.baseMapper.getPrintStorageOut(hxStorageOutParam);
    }

    @Override
    public void updatePrint(HxStorageOutParam param) {
        this.baseMapper.updatePrint(param);
    }

    @Override
    public void updatePrint2(HxStorageOutParam hxStorageOutParam) {
        this.baseMapper.updatePrint2(hxStorageOutParam);
    }

    @Override
    public List<HxStorageOutResult> findlistAllBySpec(HxStorageOutParam hxStorageOutParam, String condition, Long operateId) {
        return this.baseMapper.findlistAllBySpec(hxStorageOutParam, condition, operateId);
    }


    @Override
    public List<HxStorageOutResult> findlistAllBySpec2(HxStorageOutParam hxStorageOutParam, String condition, Long operateId) {
        return this.baseMapper.findlistAllBySpec2(hxStorageOutParam, condition, operateId);
    }

    @Override
    public HxStorageOutResult count(HxStorageOutParam hxStorageOutParam, String condition, Long operateId) {
        return this.baseMapper.count(hxStorageOutParam, condition, operateId);
    }

    @Override
    public HxStorageOutResult count2(HxStorageOutParam hxStorageOutParam, String condition, Long operateId) {
        return this.baseMapper.count2(hxStorageOutParam, condition, operateId);
    }


    @Override
    public Long findByStorageNumber(String storageNumber) {
        return this.baseMapper.findByStorageNumber(storageNumber);
    }

    @Override
    public HxStorageOutResult findReceivingBySpec(HxStorageOutParam hxStorageOutParam) {
        return this.baseMapper.findReceivingBySpec(hxStorageOutParam);
    }

    @Override
    public Integer getResid(HxStorageOutParam hxStorageOutParam) {
        Map<Long, Long> goodMap = null;
        List<HxStorageOutResult> receivingBySpecOwn = this.baseMapper.findReceivingBySpecOwn(hxStorageOutParam);

        BasicCustomer basicCustomer = null;
        if (receivingBySpecOwn != null && receivingBySpecOwn.size() > 0) {
            basicCustomer = basicCustomerService.getById(receivingBySpecOwn.get(0).getCustomerId());
        }

        if (basicCustomer == null) {
            return null;
        }

        Integer _id = null;
        HxStorageOutParam q = null;
        for (HxStorageOutResult obj : receivingBySpecOwn) {
            if (ToolUtil.isEmpty(obj.getStockPort())) {
                _id = null;
                continue;
            }
//            if ("1".equals(basicCustomer.getBoxPickMode()) && (ToolUtil.isEmpty(obj.getPrintNumb()) || "0".equals(obj.getPrintNumb()))) {
//                _id = null;
//                continue;
//            } else
            if(!"拆零".equals(obj.getScattered()) && !"1".equals(basicCustomer.getBoxPickMode()) && (ToolUtil.isEmpty(obj.getPrintNumb()) || "0".equals(obj.getPrintNumb()))){
                _id = null;
                continue;
            }
            if (_id == null) {
                _id = obj.getId();
            } else if (_id != obj.getId()) {
                return _id;
            }
//            q = new HxStorageOutParam();
//            q.setSetWarehouseId(obj.getSetWarehouseId());
//            q.setGoodsId(obj.getGoodsId());
//            //获取当前项目的所有商品可用库存
//            List<GoodNumVo> goodStockNum = this.baseMapper.getGoodStockNum(q);
//            goodMap = new HashMap<>();
//            for(GoodNumVo _obj : goodStockNum){
//                goodMap.put(_obj.getGoodId(),_obj.getNum());
//            }
//            if(goodMap.get(obj.getGoodsId()) == null || goodMap.get(obj.getGoodsId()) < Double.valueOf(obj.getGoodsNum())){
//                _id = null;
//                continue;
//            }
        }
        return _id;
    }

    @Override
    public List<HxStorageOutResult> details(HxStorageOutParam hxStorageOutParam) {
        return this.baseMapper.details(hxStorageOutParam);
    }

    @Override
    public HxStorageOutResult findcheckBySpec(HxStorageOutParam hxStorageOutParam1) {
        return this.baseMapper.findcheckBySpec(hxStorageOutParam1);
    }

    @Override
    public List<GoodNumVo> getGoodNumByHxStorageOut(HxStorageOutParam hxStorageOutParam) {
        return this.baseMapper.getGoodNumByHxStorageOut(hxStorageOutParam);
    }


    @Override
    public List<datavProResult> find(datavProResult datavProResult) {
        return this.baseMapper.find(datavProResult);
    }

    @Override
    public List<storeProResult> find1(storeProResult storeProResult) {
        return this.baseMapper.find1(storeProResult);
    }

    @Override
    public List<chukuPositionResult> findchukuposition(chukuPositionResult chukuPositionResult) {
        return this.baseMapper.findchukuposition(chukuPositionResult);
    }

    @Override
    public List<HxStorageOutResult> findJjianhuoData(HxStorageOutResult hxStorageOutResult) {
        return this.baseMapper.findJjianhuoData(hxStorageOutResult);
    }

    @Override
    public List<HxStorageOutResult> findZhijianData(HxStorageOutResult hxStorageOutResult) {
        return this.baseMapper.findZhijianData(hxStorageOutResult);
    }

    @Override
    public List<HxStorageOutResult> findDdPretendCarData(HxStorageOutResult hxStorageOutResult) {
        return this.baseMapper.findDdPretendCarData(hxStorageOutResult);
    }

    @Override
    public List<HxStorageOutResult> findPrePickOrder(List<Long> getUnit_ids) {
        return this.baseMapper.findPrePickOrder(getUnit_ids);
    }

    @Override
    public List<HxStorageOutResult> findzuoye(HxStorageOutResult hxStorageOutResult) {
        return this.baseMapper.findzuoye(hxStorageOutResult);
    }

    @Override
    public List<chukuPositionResult> findjihuoliang(chukuPositionResult chukuPositionResult) {
        return this.baseMapper.findjihuoliang(chukuPositionResult);
    }

    @Override
    public HxStorageOutResult findCountGoodsBySpec(HxStorageOutParam hxStorageOutParam) {
        return this.baseMapper.findCountGoodsBySpec(hxStorageOutParam);
    }

    @Override
    @Transactional(rollbackFor = Exception.class, timeout = 600)
    public ResponseData agvReceiving(Integer hxStorageOutId, User user) {
        //获取当前拣货单信息
        HxStorageOut hxStorageOut = this.getById(hxStorageOutId);
        //获取客户信息
        BasicCustomer basicCustomer = basicCustomerService.getById(hxStorageOut.getCustomerId());
        //获取拣货明细
        HxStorageOutDetailedParam q1 = new HxStorageOutDetailedParam();
        q1.setStorageNumber(hxStorageOut.getStorageNumber());
        List<HxStorageOutDetailedResult> outDetailedLists = this.hxStorageOutDetailedMapper.customList(q1);
        //创建AGV任务主表
        AgvStorageTask agvStorageTask = new AgvStorageTask();
        //主键
        agvStorageTask.setId(IdUtil.simpleUUID());
        //订单号
        agvStorageTask.setStorageNumber(hxStorageOut.getStorageNumber());
        //任务编号
        agvStorageTask.setTaskNo(CodeGenerateUtil.generate());
        //AGV机器人类型
        if ("1".equals(hxStorageOut.getAgvRobot())) { //海康
            agvStorageTask.setAgvTyp("HIK");
            //暂时写死 目标点
//            agvStorageTask.setWebCode("2CS");
            agvStorageTask.setWebCode(hxStorageOut.getStockPort());
        } else if ("2".equals(hxStorageOut.getAgvRobot())) { //TUSK
            agvStorageTask.setAgvTyp("TUSK");
            //暂时写死 目标点
            agvStorageTask.setWebCode("H" + StringUtils.leftPad(hxStorageOut.getStockPort(), 3, "0"));
        }
        // 是否开启任务运行限制 启用 禁用
        agvStorageTask.setAgvTaskRunFlag(basicCustomer.getAgvTaskRunFlag());
        //创建人
        if (user != null) {
            agvStorageTask.setCreateUser(user.getAccount());
        }
        //基础URL
        if (basicCustomer != null && ToolUtil.isNotEmpty(basicCustomer.getAgvBaseUrl())) {
            agvStorageTask.setAgvApiBaseUrl(basicCustomer.getAgvBaseUrl());
        }
        //创建时间
        agvStorageTask.setCreateTime(new Date());
        //交付客户id
        agvStorageTask.setDeliverId(hxStorageOut.getDeliverId());
        //部门id
        agvStorageTask.setDeptId(hxStorageOut.getDeptId());
        //发货仓库id
        agvStorageTask.setSetWarehouseId(hxStorageOut.getSetWarehouseId());
        //是否拆托 默认否
        agvStorageTask.setDisPallet("否");
        //新增
        this.agvStorageTaskMapper.insert(agvStorageTask);
        //明细
        List<AgvStorageTaskDetail> saveList = new ArrayList<>();
        AgvStorageTaskDetail agvStorageTaskDetail = null;
        for (HxStorageOutDetailedResult obj : outDetailedLists) {
            agvStorageTaskDetail = new AgvStorageTaskDetail();
            agvStorageTaskDetail.setId(IdUtil.simpleUUID()); //主键
            agvStorageTaskDetail.setStorageTaskId(agvStorageTask.getId()); //agv拣货任务ID
            agvStorageTaskDetail.setStorageOutDetailId(obj.getId().longValue()); //拣货明细ID
            agvStorageTaskDetail.setPositionId(obj.getPositionId()); //库位id
            agvStorageTaskDetail.setPositionNumber(obj.getPositionNumber());
            agvStorageTaskDetail.setPositionPickingorder(Integer.valueOf(obj.getPositionPickingorder()));
            agvStorageTaskDetail.setGoodsId(obj.getGoodsId());
            agvStorageTaskDetail.setGoodsNumber(obj.getGoodsNumber());
            agvStorageTaskDetail.setGoodsName(obj.getGoodsName());
            agvStorageTaskDetail.setUnit(obj.getUnit());
            agvStorageTaskDetail.setRate(new BigDecimal(obj.getRate()));
            agvStorageTaskDetail.setNum(new BigDecimal(obj.getNum()).setScale(3, BigDecimal.ROUND_HALF_UP));
            saveList.add(agvStorageTaskDetail);
        }
        //批量保存
        if (saveList != null && saveList.size() > 0) {
            this.agvStorageTaskDetailService.saveBatch(saveList);
        }
        HxStorageOutParam update = new HxStorageOutParam();
        update.setId(hxStorageOutId);
        update.setStorageState("拣货中");
        update.setStorageUser(user.getAccount());
        update.setStorageUserName(user.getName());
        update.setStorageTime(new Date());
        this.update(update);
        return ResponseData.success(hxStorageOutId);
    }

    @Override
    public ResponseData agvGetPosition(Integer hxStorageOutId) {
        //循环查找对应的库位
        Map<String, Object> rsMap = new HashedMap();
        //根据拣货单ID获取拣货单信息
        HxStorageOut hxStorageOut = this.getById(hxStorageOutId);
        if (hxStorageOut == null) {
            return ResponseData.error("拣货任务不存在");
        }

        //根据拣货单编号获取AGV拣货任务单信息
        AgvStorageTaskResult agvStorageTask = this.agvStorageTaskMapper.findTaskByStorageNum(AgvStorageTaskParam.builder()
                .storageNumber(hxStorageOut.getStorageNumber())
                .setWarehouseId(hxStorageOut.getSetWarehouseId())
                .build());
        rsMap.put("storageNumber", hxStorageOut.getStorageNumber());
        rsMap.put("associationOrder", hxStorageOut.getAssociationOrder());
        if (ToolUtil.isEmpty(hxStorageOut.getStorageUserName())) {
            rsMap.put("storageUserName", "--");
        } else {
            rsMap.put("storageUserName", hxStorageOut.getStorageUserName());
        }

        if (agvStorageTask == null) {
            return ResponseData.error("AGV拣货任务不存在");
        } else if ("20".equals(agvStorageTask.getStat())) {
            rsMap.put("agvNo", agvStorageTask.getAgvNo());
            rsMap.put("goodsInfo", StoragePostionVo.builder()
                    .stat("20")
                    .goodsName("-")
                    .goodsNumber("-")
                    .positionNumber("-")
                    .unit("-")
                    .storageTaskId(agvStorageTask.getId())
                    .num(new BigDecimal(0))
                    .build());
            return ResponseData.success(rsMap);
        } else {
            rsMap.put("agvNo", agvStorageTask.getAgvNo());
        }

        //根据拣货单获取拣货单中未拣商品和对应库位
        List<AgvStorageTaskDetailResult> agvStorageTaskDetailList = this.agvStorageTaskDetailMapper.getNextTaskGoodList(AgvStorageTaskDetailParam.builder()
                .storageTaskId(agvStorageTask.getId())
                .picked("否")
                .limit(" 1 ")
                .build());
        if (agvStorageTaskDetailList == null || agvStorageTaskDetailList.size() < 1) {
            rsMap.put("goodsInfo", StoragePostionVo.builder()
                    .stat("20")
                    .goodsName("-")
                    .goodsNumber("-")
                    .positionNumber("-")
                    .unit("-")
                    .num(new BigDecimal(0))
                    .storageTaskId(agvStorageTask.getId())
                    .build());
//            return ResponseData.success(rsMap);
        } else {
            rsMap.put("goodsInfo", StoragePostionVo.builder()
                    .id(agvStorageTaskDetailList.get(0).getId())
                    .storageTaskId(agvStorageTaskDetailList.get(0).getStorageTaskId())
                    .storageOutDetailId(agvStorageTaskDetailList.get(0).getStorageOutDetailId())
                    .positionNumber(agvStorageTaskDetailList.get(0).getPositionNumber())
                    .num(agvStorageTaskDetailList.get(0).getNum())
                    .goodsNumber(agvStorageTaskDetailList.get(0).getGoodsNumber())
                    .goodsName(agvStorageTaskDetailList.get(0).getGoodsName())
                    .goodsId(agvStorageTaskDetailList.get(0).getGoodsId())
                    .stat(agvStorageTask.getStat())
                    .unit(agvStorageTaskDetailList.get(0).getUnit())
                    .build());
//            return ResponseData.success(rsMap);
//            _storagePostionVo = new StoragePostionVo();
//            _storagePostionVo.setId(obj.getId());
//            _storagePostionVo.setStorageTaskId(obj.getStorageTaskId());
//            _storagePostionVo.setStorageOutDetailId(obj.getStorageOutDetailId());
//            _storagePostionVo.setPositionNumber(obj.getPositionNumber());
//            _storagePostionVo.setNum(obj.getNum().subtract(obj.getRealNum()));
//            _storagePostionVo.setGoodsNumber(obj.getGoodsNumber());
//            _storagePostionVo.setGoodsName(obj.getGoodsName());
//            _storagePostionVo.setGoodsId(obj.getGoodsId());
//            _storagePostionVo.setStat(agvStorageTask.getStat());
//            _storagePostionVo.setUnit(obj.getUnit());
        }
//        Map<String, AgvStorageTaskDetailResult> agvStorageTaskDetailMap = new HashedMap();
//        for (AgvStorageTaskDetailResult obj : agvStorageTaskDetailList) {
//            agvStorageTaskDetailMap.put(obj.getPositionNumber(), obj);
//        }
        //仓库对应的库位排布
//        List<AgvStoragePositionResult> agvStoragePositionResults = agvStoragePositionMapper.customList(AgvStoragePositionParam.builder()
//                .setWarehouseId(hxStorageOut.getSetWarehouseId())
//                .orderStr("passageway,select_ord")
//                .build());
//        Map<String, AgvStoragePositionResult> agvStoragePositionMap = new HashedMap();
//        for (AgvStoragePositionResult obj : agvStoragePositionResults) {
//            agvStoragePositionMap.put(obj.getPositionNumber(), obj);
//        }

//        List<StoragePostionShowVo> storagePostionShowVoList = new ArrayList<>();
//        StoragePostionShowVo _storagePostionShowVo = null;
//        StoragePostionVo _storagePostionVo = null;
//        AgvStoragePositionResult agvStoragePositionResult = null;
//        Map<String, String> addMap = new HashedMap();
//        for (AgvStorageTaskDetailResult obj : agvStorageTaskDetailList) {
//            //如果已添加 跳过
//            if (addMap.get(obj.getPositionNumber()) != null) {
//                continue;
//            }
//            //如果超过2个 终止
//            if (storagePostionShowVoList.size() > 1) {
//                break;
//            }
//            agvStoragePositionResult = agvStoragePositionMap.get(obj.getPositionNumber());
//            if (agvStoragePositionResult == null) {
//                return ResponseData.error("AGV拣货库位中未发现拣选库位【" + obj.getPositionNumber() + "】，请即使维护");
//            }
//            _storagePostionVo = new StoragePostionVo();
//            _storagePostionVo.setId(obj.getId());
//            _storagePostionVo.setStorageTaskId(obj.getStorageTaskId());
//            _storagePostionVo.setStorageOutDetailId(obj.getStorageOutDetailId());
//            _storagePostionVo.setPositionNumber(obj.getPositionNumber());
//            _storagePostionVo.setNum(obj.getNum().subtract(obj.getRealNum()));
//            _storagePostionVo.setGoodsNumber(obj.getGoodsNumber());
//            _storagePostionVo.setGoodsName(obj.getGoodsName());
//            _storagePostionVo.setGoodsId(obj.getGoodsId());
//            _storagePostionVo.setStat(agvStorageTask.getStat());
//            _storagePostionVo.setUnit(obj.getUnit());
//            if (addMap.size() < 1) {
//                _storagePostionVo.setTaskFlag(1);
//                _storagePostionVo.setPClass("demo-layout bg-purple-bule");
//                rsMap.put("goodsInfo", _storagePostionVo);
//            }
//            _storagePostionShowVo = new StoragePostionShowVo();
//            storagePostionShowVoList.add(_storagePostionShowVo);
//            if ("左".equals(agvStoragePositionResult.getAbout())) {
//                _storagePostionShowVo.setLeftVo(_storagePostionVo);
//            } else {
//                _storagePostionShowVo.setRightVo(_storagePostionVo);
//            }
//            addMap.put(obj.getPositionNumber(), obj.getPositionNumber());
//            //根据左边库位，找到对应的右侧库位
//            String pStr1 = obj.getPositionNumber().substring(2, 4);
//            String pStr2 = agvStoragePositionResult.getPassageway().replaceAll(pStr1, "");
//            if (ToolUtil.isNotEmpty(pStr2)) {
//                String rightPositionNumber = obj.getPositionNumber().substring(0, 2) + pStr2 + obj.getPositionNumber().substring(4);
//                if (agvStoragePositionMap.get(rightPositionNumber) != null && agvStorageTaskDetailMap.get(rightPositionNumber) != null) {
//                    _storagePostionVo = new StoragePostionVo();
//                    _storagePostionVo.setId(agvStorageTaskDetailMap.get(rightPositionNumber).getId());
//                    _storagePostionVo.setStorageTaskId(agvStorageTaskDetailMap.get(rightPositionNumber).getStorageTaskId());
//                    _storagePostionVo.setStorageOutDetailId(agvStorageTaskDetailMap.get(rightPositionNumber).getStorageOutDetailId());
//                    _storagePostionVo.setPositionNumber(agvStorageTaskDetailMap.get(rightPositionNumber).getPositionNumber());
//                    _storagePostionVo.setNum(agvStorageTaskDetailMap.get(rightPositionNumber).getNum().subtract(agvStorageTaskDetailMap.get(rightPositionNumber).getRealNum()));
//                    _storagePostionVo.setGoodsNumber(agvStorageTaskDetailMap.get(rightPositionNumber).getGoodsNumber());
//                    _storagePostionVo.setGoodsName(agvStorageTaskDetailMap.get(rightPositionNumber).getGoodsName());
//                    _storagePostionVo.setGoodsId(agvStorageTaskDetailMap.get(rightPositionNumber).getGoodsId());
//                    _storagePostionVo.setUnit(agvStorageTaskDetailMap.get(rightPositionNumber).getUnit());
//                    if ("左".equals(agvStoragePositionResult.getAbout())) {
//                        _storagePostionShowVo.setRightVo(_storagePostionVo);
//
//                    } else {
//                        _storagePostionShowVo.setLeftVo(_storagePostionVo);
//                    }
//                    addMap.put(agvStorageTaskDetailMap.get(rightPositionNumber).getPositionNumber(), agvStorageTaskDetailMap.get(rightPositionNumber).getPositionNumber());
//                } else {
//                    _storagePostionVo = new StoragePostionVo();
//                    _storagePostionVo.setPositionNumber(rightPositionNumber);
//                    if ("左".equals(agvStoragePositionResult.getAbout())) {
//                        _storagePostionShowVo.setRightVo(_storagePostionVo);
//
//                    } else {
//                        _storagePostionShowVo.setLeftVo(_storagePostionVo);
//                    }
//                }
//            } else {
//                _storagePostionVo = new StoragePostionVo();
//                _storagePostionVo.setPositionNumber("无");
//                if ("左".equals(agvStoragePositionResult.getAbout())) {
//                    _storagePostionShowVo.setRightVo(_storagePostionVo);
//
//                } else {
//                    _storagePostionShowVo.setLeftVo(_storagePostionVo);
//                }
//            }
//        }
//        //倒序
//        if (storagePostionShowVoList != null && storagePostionShowVoList.size() > 0) {
//            Collections.reverse(storagePostionShowVoList);
//        }
//        //循环查找对应的库位
//        rsMap.put("dataList", storagePostionShowVoList);
        return ResponseData.success(rsMap);
    }

    /**
     * AGV开始拣货，取托盘和到第一个拣货位置
     *
     * @param agvStorageTaskDetailId
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class, timeout = 180)
    public ResponseData agvStorageStart(String agvStorageTaskDetailId) {
        //根据明细ID获取明细数据
        AgvStorageTaskDetail agvStorageTaskDetail = agvStorageTaskDetailService.getById(agvStorageTaskDetailId);
        if (agvStorageTaskDetail == null) {
            return ResponseData.error("AGV拣货任务不存在，无法执行该操作");
        }

        //根据明细ID中的agv任务ID获取AGV拣货任务信息
        AgvStorageTask agvStorageTask = agvStorageTaskService.getById(agvStorageTaskDetail.getStorageTaskId());
        if (agvStorageTask == null) {
            return ResponseData.error("AGV拣货任务不存在，无法执行该操作");
        }
        //如果没有地址则需要再客户上进行先进行维护
        if (ToolUtil.isEmpty(agvStorageTask.getAgvApiBaseUrl())) {
            return ResponseData.error("客户信息中未维护机器人信息，无法执行该操作");
        }
        // 小车运行限制
        if ("启用".equals(agvStorageTask.getAgvTaskRunFlag()) && "99".equals(agvStorageTask.getTaskStat())) {
            return ResponseData.error("当前操作不可执行，请等待小车运行完上次任务！");
        }
        /**
         * 根据库位编号，获取APR编号
         */
        AgvStoragePosition agvStoragePosition = agvStoragePositionService.lambdaQuery()
                .eq(AgvStoragePosition::getSetWarehouseId, agvStorageTask.getSetWarehouseId())
                .eq(AgvStoragePosition::getPositionNumber, agvStorageTaskDetail.getPositionNumber())
                .one();
        //如果是海康机器人
        if ("HIK".equals(agvStorageTask.getAgvTyp())) {
            //封装接口信息
            HikAgvTaskParam param = new HikAgvTaskParam();
            param.setTaskNo(agvStorageTask.getTaskNo());
            param.setPositionType("1");
            param.setStartArea(agvStoragePosition.getAgvPick());
            param.setEndcargoInfo(agvStoragePosition.getAprCode());
            HikRsVo hikRsVo = HikApiUtils.genctnrBinTask(agvStorageTask.getAgvApiBaseUrl(), param);
            if (hikRsVo == null) {
                return ResponseData.error("接口调用错误");
            } else if (!"0".equals(hikRsVo.getCode())) {
                return ResponseData.error(hikRsVo.getMessage());
            }
        } else if ("TUSK".equals(agvStorageTask.getAgvTyp())) {
            CreateSortParam param = new CreateSortParam();
            param.setTaskId(agvStorageTask.getTaskNo());
            //取托盘
            param.getTargetActions().add(TargetActionsVo.builder()
                    .target(agvStoragePosition.getAgvPick())
                    .action("GET")
                    .build());

            String positionNumber = null;
            if (agvStoragePosition != null) {
                positionNumber = agvStoragePosition.getAprCode();
            } else {
                positionNumber = agvStorageTaskDetail.getPositionNumber();
            }
            //取货点
            param.getTargetActions().add(TargetActionsVo.builder()
                    .target(positionNumber)
                    .action("MOVE")
                    .build());
            TuskRsVo tuskRs = TustApiUtils.createSortTask(agvStorageTask.getAgvApiBaseUrl(), param);
            if (tuskRs == null) {
                return ResponseData.error("接口调用错误");
            } else if (tuskRs.getCode() != 200) {
                return ResponseData.error(tuskRs.getMsg());
            }
        }

        //修改拣货状态
        AgvStorageTaskParam update = new AgvStorageTaskParam();
        update.setId(agvStorageTask.getId());
        update.setStat("10");
//        update.setCurrTask(agvStorageTaskDetail.getId());
//        agvStorageTaskService.update(update);
        return ResponseData.success(agvStorageTaskService.getById(agvStorageTask.getId()));
    }

    @Transactional(rollbackFor = Exception.class, timeout = 180)
    public ResponseData agvStorageFirst(String agvStorageTaskDetailId) {
        //根据明细ID获取明细数据
        AgvStorageTaskDetail agvStorageTaskDetail = agvStorageTaskDetailService.getById(agvStorageTaskDetailId);
        if (agvStorageTaskDetail == null) {
            return ResponseData.error("AGV拣货任务不存在，无法执行该操作");
        }

        //根据明细ID中的agv任务ID获取AGV拣货任务信息
        AgvStorageTask agvStorageTask = agvStorageTaskService.getById(agvStorageTaskDetail.getStorageTaskId());
        if (agvStorageTask == null) {
            return ResponseData.error("AGV拣货任务不存在，无法执行该操作");
        }
        //如果没有地址则需要再客户上进行先进行维护
        if (ToolUtil.isEmpty(agvStorageTask.getAgvApiBaseUrl())) {
            return ResponseData.error("客户信息中未维护机器人信息，无法执行该操作");
        }
        // 小车运行限制
        if ("启用".equals(agvStorageTask.getAgvTaskRunFlag()) && "99".equals(agvStorageTask.getTaskStat())) {
            return ResponseData.error("当前操作不可执行，请等待小车运行完上次任务！");
        }

        //如果是海康机器人
        HikAgvTaskParam param = new HikAgvTaskParam();
        param.setTaskNo(agvStorageTask.getTaskNo());
        param.setPositionType("2");
        param.setEndcargoInfo(agvStorageTaskDetail.getPositionNumber());
        HikRsVo hikRsVo = HikApiUtils.genctnrBinTask(agvStorageTask.getAgvApiBaseUrl(), param);
        if (hikRsVo == null) {
            return ResponseData.error("接口调用错误");
        } else if (!"0".equals(hikRsVo.getCode())) {
            return ResponseData.error(hikRsVo.getMessage());
        }

        //修改拣货状态
        AgvStorageTaskParam update = new AgvStorageTaskParam();
        update.setId(agvStorageTask.getId());
        update.setStat("10");
        update.setCurrTask(agvStorageTaskDetail.getId());
        agvStorageTaskService.update(update);
        return ResponseData.success(agvStorageTaskService.getById(agvStorageTask.getId()));
    }

    /**
     * 开始执行下一步
     * 首先完成拣货数量
     * 然后寻找下一个任务的库位
     *
     * @param agvStorageTaskDetailParam
     * @return
     */
    @Transactional(rollbackFor = Exception.class, timeout = 180)
    public ResponseData agvStorageNext(AgvStorageTaskDetailParam agvStorageTaskDetailParam, User user) {
        //根据明细ID获取明细数据
        AgvStorageTaskDetail agvStorageTaskDetail = agvStorageTaskDetailService.getById(agvStorageTaskDetailParam.getId());
        if (agvStorageTaskDetail == null) {
            return ResponseData.error("AGV拣货任务不存在，无法执行该操作");
        }

        //根据明细ID中的agv任务ID获取AGV拣货任务信息
        AgvStorageTask agvStorageTask = agvStorageTaskService.getById(agvStorageTaskDetail.getStorageTaskId());
        if (agvStorageTask == null) {
            return ResponseData.error("AGV拣货任务不存在，无法执行该操作");
        }

        // 小车运行限制
        if ("启用".equals(agvStorageTask.getAgvTaskRunFlag()) && "99".equals(agvStorageTask.getTaskStat())) {
            return ResponseData.error("当前操作不可执行，请等待小车运行完上次任务！");
        }

        //修改拣货数量
        AgvStorageTaskDetailParam updateAgvStorageTaskDetail = new AgvStorageTaskDetailParam();
        updateAgvStorageTaskDetail.setId(agvStorageTaskDetail.getId());
        if (ToolUtil.isNotEmpty(agvStorageTaskDetailParam.getRealNum())) {
            updateAgvStorageTaskDetail.setRealNum(agvStorageTaskDetailParam.getRealNum());
        } else {
            updateAgvStorageTaskDetail.setRealNum(agvStorageTaskDetail.getNum());
        }
        updateAgvStorageTaskDetail.setStorageTime(new Date());
        updateAgvStorageTaskDetail.setStorageUserAcct(user.getAccount());
        updateAgvStorageTaskDetail.setStorageUserName(user.getName());

        //修改明细
        agvStorageTaskDetailMapper.updateRealNum(updateAgvStorageTaskDetail);
        //修改拣货明细
        hxStorageOutDetailedService.lambdaUpdate()
                .eq(HxStorageOutDetailed::getStorageNumber, agvStorageTask.getStorageNumber())
                .setSql("real_num = num ")
                .update();
        //寻找下一个任务
        AgvStorageTaskDetailParam q = new AgvStorageTaskDetailParam();
        q.setPositionPickingorderMin(agvStorageTaskDetail.getPositionPickingorder());
        q.setStorageTaskId(agvStorageTaskDetail.getStorageTaskId());
        q.setPicked("否");
        AgvStorageTaskDetailResult nextTaskGood = agvStorageTaskDetailMapper.getNextTaskGood(q);
        if (nextTaskGood != null) {
            //当前位置的APR编号
            AgvStoragePosition agvStoragePositionCurr = agvStoragePositionService.lambdaQuery()
                    .eq(AgvStoragePosition::getSetWarehouseId, agvStorageTask.getSetWarehouseId())
                    .eq(AgvStoragePosition::getPositionNumber, agvStorageTaskDetail.getPositionNumber())
                    .one();

            /**
             * 根据库位编号，获取APR编号
             */
            AgvStoragePosition agvStoragePosition = agvStoragePositionService.lambdaQuery()
                    .eq(AgvStoragePosition::getSetWarehouseId, agvStorageTask.getSetWarehouseId())
                    .eq(AgvStoragePosition::getPositionNumber, nextTaskGood.getPositionNumber())
                    .one();
            boolean sendApi = true;
//            if(agvStoragePositionCurr != null && agvStoragePosition !=null
//                    && ToolUtil.isNotEmpty(agvStoragePositionCurr.getAprCode()) && ToolUtil.isNotEmpty(agvStoragePosition.getAprCode()) && agvStoragePositionCurr.getAprCode().equals(agvStoragePosition.getAprCode())){
//                sendApi = false;
//            }
            if (sendApi) {
                //如果是海康机器人
                if ("HIK".equals(agvStorageTask.getAgvTyp())) {
                    //封装接口信息
                    HikAgvTaskParam param = new HikAgvTaskParam();
                    param.setTaskNo(agvStorageTask.getTaskNo());
                    param.setPositionType("2");
                    param.setEndcargoInfo(nextTaskGood.getPositionNumber());
                    HikRsVo hikRsVo = HikApiUtils.genctnrBinTask(agvStorageTask.getAgvApiBaseUrl(), param);
                    if (hikRsVo == null) {
                        return ResponseData.error("接口调用错误");
                    } else if (!"0".equals(hikRsVo.getCode()) && !hikRsVo.getMessage().contains("不需要下发任务")) {
                        return ResponseData.error(hikRsVo.getMessage());
                    }
                } else if ("TUSK".equals(agvStorageTask.getAgvTyp())) {
                    CreateSortParam param = new CreateSortParam();
                    param.setTaskId(agvStorageTask.getTaskNo());

                    String positionNumber = null;
                    if (agvStoragePosition != null) {
                        positionNumber = agvStoragePosition.getAprCode();
                    } else {
                        positionNumber = nextTaskGood.getPositionNumber();
                    }
                    //取货点
                    param.getTargetActions().add(TargetActionsVo.builder()
                            .target(positionNumber)
                            .action("MOVE")
                            .build());
                    TuskRsVo tuskRs = TustApiUtils.createSortTask(agvStorageTask.getAgvApiBaseUrl(), param);
                    if (tuskRs == null) {
                        return ResponseData.error("接口调用错误");
                    } else if (tuskRs.getCode() != 200) {
                        return ResponseData.error(tuskRs.getMsg());
                    }
                }
            }
            AgvStorageTask updateAgvStorageTask = new AgvStorageTask();
            updateAgvStorageTask.setId(nextTaskGood.getStorageTaskId());
            updateAgvStorageTask.setCurrTask(nextTaskGood.getId());
            if ("启用".equals(agvStorageTask.getAgvTaskRunFlag())) {
                updateAgvStorageTask.setTaskStat("99");
            }
            agvStorageTaskMapper.updateById(updateAgvStorageTask);

        } else {
            q = new AgvStorageTaskDetailParam();
            q.setStorageTaskId(agvStorageTaskDetail.getStorageTaskId());
            q.setPicked("否");
            AgvStorageTaskDetailResult nextTaskGood1 = agvStorageTaskDetailMapper.getNextTaskGood(q);
            if (nextTaskGood1 == null) {
                AgvStorageTask updateAgvStorageTask = new AgvStorageTask();
                updateAgvStorageTask.setId(agvStorageTask.getId());
                updateAgvStorageTask.setStat("20");
                updateAgvStorageTask.setTaskStat("00");
                agvStorageTaskMapper.updateById(updateAgvStorageTask);
                return ResponseData.success(666, "拣货任务已完成，请送达巷道", null);
            } else {
                //当前位置的APR编号
                AgvStoragePosition agvStoragePositionCurr = agvStoragePositionService.lambdaQuery()
                        .eq(AgvStoragePosition::getSetWarehouseId, agvStorageTask.getSetWarehouseId())
                        .eq(AgvStoragePosition::getPositionNumber, agvStorageTaskDetail.getPositionNumber())
                        .one();

                /**
                 * 根据库位编号，获取APR编号
                 */
                AgvStoragePosition agvStoragePosition = agvStoragePositionService.lambdaQuery()
                        .eq(AgvStoragePosition::getSetWarehouseId, agvStorageTask.getSetWarehouseId())
                        .eq(AgvStoragePosition::getPositionNumber, nextTaskGood1.getPositionNumber())
                        .one();
                boolean sendApi = true;
                if (agvStoragePositionCurr != null && agvStoragePosition != null
                        && ToolUtil.isNotEmpty(agvStoragePositionCurr.getAprCode()) && ToolUtil.isNotEmpty(agvStoragePosition.getAprCode()) && agvStoragePositionCurr.getAprCode().equals(agvStoragePosition.getAprCode())) {
                    sendApi = false;
                }
                if (sendApi) {
                    //如果是海康机器人
                    if ("HIK".equals(agvStorageTask.getAgvTyp())) {
                        //封装接口信息
                        HikAgvTaskParam param = new HikAgvTaskParam();
                        param.setTaskNo(agvStorageTask.getTaskNo());
                        param.setPositionType("2");
                        param.setEndcargoInfo(nextTaskGood1.getPositionNumber());
                        HikRsVo hikRsVo = HikApiUtils.genctnrBinTask(agvStorageTask.getAgvApiBaseUrl(), param);
                        if (hikRsVo == null) {
                            return ResponseData.error("接口调用错误");
                        } else if (!"0".equals(hikRsVo.getCode())) {
                            return ResponseData.error(hikRsVo.getMessage());
                        }
                    } else if ("TUSK".equals(agvStorageTask.getAgvTyp())) {
                        CreateSortParam param = new CreateSortParam();
                        param.setTaskId(agvStorageTask.getTaskNo());
                        String positionNumber = null;
                        if (agvStoragePosition != null) {
                            positionNumber = agvStoragePosition.getAprCode();
                        } else {
                            positionNumber = nextTaskGood1.getPositionNumber();
                        }
                        //取货点
                        param.getTargetActions().add(TargetActionsVo.builder()
                                .target(positionNumber)
                                .action("MOVE")
                                .build());
                        TuskRsVo tuskRs = TustApiUtils.createSortTask(agvStorageTask.getAgvApiBaseUrl(), param);
                        if (tuskRs == null) {
                            return ResponseData.error("接口调用错误");
                        } else if (tuskRs.getCode() != 200) {
                            return ResponseData.error(tuskRs.getMsg());
                        }
                    }
                }

                AgvStorageTask updateAgvStorageTask = new AgvStorageTask();
                updateAgvStorageTask.setId(nextTaskGood1.getStorageTaskId());
                updateAgvStorageTask.setCurrTask(nextTaskGood1.getId());
                if ("启用".equals(agvStorageTask.getAgvTaskRunFlag())) {
                    updateAgvStorageTask.setTaskStat("99");
                }
                agvStorageTaskMapper.updateById(updateAgvStorageTask);
            }
        }
        return ResponseData.success();
    }

    /**
     * 跳过当前任务，并移动到下一任务
     *
     * @param agvStorageTaskDetailParam
     * @return
     */

    @Transactional(rollbackFor = Exception.class, timeout = 180)
    public ResponseData agvStorageJump(AgvStorageTaskDetailParam agvStorageTaskDetailParam) {

        //根据明细ID获取明细数据
        AgvStorageTaskDetail agvStorageTaskDetail = agvStorageTaskDetailService.getById(agvStorageTaskDetailParam.getId());
        if (agvStorageTaskDetail == null) {
            return ResponseData.error("AGV拣货任务不存在，无法执行该操作");
        }

        //根据明细ID中的agv任务ID获取AGV拣货任务信息
        AgvStorageTask agvStorageTask = agvStorageTaskService.getById(agvStorageTaskDetail.getStorageTaskId());
        if (agvStorageTask == null) {
            return ResponseData.error("AGV拣货任务不存在，无法执行该操作");
        }
        // 小车运行限制
        if ("启用".equals(agvStorageTask.getAgvTaskRunFlag()) && "99".equals(agvStorageTask.getTaskStat())) {
            return ResponseData.error("当前操作不可执行，请等待小车运行完上次任务！");
        }
        //寻找下一个任务
        AgvStorageTaskDetailParam q = new AgvStorageTaskDetailParam();
        q.setPositionPickingorderMin(agvStorageTaskDetail.getPositionPickingorder());
        q.setStorageTaskId(agvStorageTaskDetail.getStorageTaskId());
        q.setPicked("否");
        AgvStorageTaskDetailResult nextTaskGood = agvStorageTaskDetailMapper.getNextTaskGood(q);
        if (nextTaskGood != null) {
            //如果是海康机器人
            if ("HIK".equals(agvStorageTask.getAgvTyp())) {
                //封装接口信息
                HikAgvTaskParam param = new HikAgvTaskParam();
                param.setTaskNo(agvStorageTask.getTaskNo());
                param.setPositionType("2");
                param.setEndcargoInfo(nextTaskGood.getPositionNumber());
                HikRsVo hikRsVo = HikApiUtils.genctnrBinTask(agvStorageTask.getAgvApiBaseUrl(), param);
                if (hikRsVo == null) {
                    return ResponseData.error("接口调用错误");
                } else if (!"0".equals(hikRsVo.getCode())) {
                    return ResponseData.error(hikRsVo.getMessage());
                }
            } else if ("TUSK".equals(agvStorageTask.getAgvTyp())) {
                CreateSortParam param = new CreateSortParam();
                param.setTaskId(agvStorageTask.getTaskNo());

                /**
                 * 根据库位编号，获取APR编号
                 */
                AgvStoragePosition agvStoragePosition = agvStoragePositionService.lambdaQuery()
                        .eq(AgvStoragePosition::getSetWarehouseId, agvStorageTask.getSetWarehouseId())
                        .eq(AgvStoragePosition::getPositionNumber, nextTaskGood.getPositionNumber())
                        .one();
                String positionNumber = null;
                if (agvStoragePosition != null) {
                    positionNumber = agvStoragePosition.getAprCode();
                } else {
                    positionNumber = nextTaskGood.getPositionNumber();
                }
                //取货点
                TuskRsVo tuskRs = TustApiUtils.changeTask(agvStorageTask.getAgvApiBaseUrl(), ChangeTaskParam.builder()
                        .taskId(agvStorageTask.getTaskNo())
                        .target(positionNumber)
                        .build());
                if (tuskRs == null) {
                    return ResponseData.error("接口调用错误");
                } else if (tuskRs.getCode() != 200) {
                    return ResponseData.error(tuskRs.getMsg());
                }
            }

            AgvStorageTask updateAgvStorageTask = new AgvStorageTask();
            updateAgvStorageTask.setId(nextTaskGood.getStorageTaskId());
            updateAgvStorageTask.setCurrTask(nextTaskGood.getId());
            if ("启用".equals(agvStorageTask.getAgvTaskRunFlag())) {
                updateAgvStorageTask.setTaskStat("99");
            }
            agvStorageTaskMapper.updateById(updateAgvStorageTask);
        } else {
            q = new AgvStorageTaskDetailParam();
            q.setStorageTaskId(agvStorageTaskDetail.getStorageTaskId());
            q.setPicked("否");
            AgvStorageTaskDetailResult nextTaskGood1 = agvStorageTaskDetailMapper.getNextTaskGood(q);
            if (nextTaskGood1 == null) {
                AgvStorageTask updateAgvStorageTask = new AgvStorageTask();
                updateAgvStorageTask.setId(agvStorageTask.getId());
                updateAgvStorageTask.setStat("20");
                updateAgvStorageTask.setTaskStat("00");
                agvStorageTaskMapper.updateById(updateAgvStorageTask);
                return ResponseData.success(666, "拣货任务已完成，请送达巷道", null);
            } else {
                if (nextTaskGood1.getId().equals(agvStorageTaskDetailParam.getId())) {
                    return ResponseData.error("当前任务是最后一个拣货商品，不可跳过！！");
                }
                //如果是海康机器人
                if ("HIK".equals(agvStorageTask.getAgvTyp())) {
                    //封装接口信息
                    HikAgvTaskParam param = new HikAgvTaskParam();
                    param.setTaskNo(agvStorageTask.getTaskNo());
                    param.setPositionType("2");
                    param.setEndcargoInfo(nextTaskGood1.getPositionNumber());
                    HikRsVo hikRsVo = HikApiUtils.genctnrBinTask(agvStorageTask.getAgvApiBaseUrl(), param);
                    if (hikRsVo == null) {
                        return ResponseData.error("接口调用错误");
                    } else if (!"0".equals(hikRsVo.getCode())) {
                        return ResponseData.error(hikRsVo.getMessage());
                    }
                } else if ("TUSK".equals(agvStorageTask.getAgvTyp())) {
                    CreateSortParam param = new CreateSortParam();
                    param.setTaskId(agvStorageTask.getTaskNo());

                    /**
                     * 根据库位编号，获取APR编号
                     */
                    AgvStoragePosition agvStoragePosition = agvStoragePositionService.lambdaQuery()
                            .eq(AgvStoragePosition::getSetWarehouseId, agvStorageTask.getSetWarehouseId())
                            .eq(AgvStoragePosition::getPositionNumber, nextTaskGood1.getPositionNumber())
                            .one();
                    String positionNumber = null;
                    if (agvStoragePosition != null) {
                        positionNumber = agvStoragePosition.getAprCode();
                    } else {
                        positionNumber = nextTaskGood1.getPositionNumber();
                    }
                    //取货点
                    param.getTargetActions().add(TargetActionsVo.builder()
                            .target(positionNumber)
                            .action("MOVE")
                            .build());
                    TuskRsVo tuskRs = TustApiUtils.createSortTask(agvStorageTask.getAgvApiBaseUrl(), param);
                    if (tuskRs == null) {
                        return ResponseData.error("接口调用错误");
                    } else if (tuskRs.getCode() != 200) {
                        return ResponseData.error(tuskRs.getMsg());
                    }
                }
                AgvStorageTask updateAgvStorageTask = new AgvStorageTask();
                updateAgvStorageTask.setId(nextTaskGood1.getStorageTaskId());
                updateAgvStorageTask.setCurrTask(nextTaskGood1.getId());
                if ("启用".equals(agvStorageTask.getAgvTaskRunFlag())) {
                    updateAgvStorageTask.setTaskStat("99");
                }
                agvStorageTaskMapper.updateById(updateAgvStorageTask);
            }
        }
        return ResponseData.success();
    }


    /**
     * 送达巷道
     *
     * @param agvStorageTaskId
     * @return
     */
    @Transactional(rollbackFor = Exception.class, timeout = 180)
    public ResponseData agvStorageToWay(String agvStorageTaskId) {
        //根据明细ID中的agv任务ID获取AGV拣货任务信息
        AgvStorageTask agvStorageTask = agvStorageTaskService.getById(agvStorageTaskId);
        if (agvStorageTask == null) {
            return ResponseData.error("AGV拣货任务不存在，无法执行该操作");
        }

        //如果是海康机器人
        if ("HIK".equals(agvStorageTask.getAgvTyp())) {
            //封装接口信息
            HikAgvTaskParam param = new HikAgvTaskParam();
            param.setTaskNo(agvStorageTask.getTaskNo());
            param.setPositionType("3");
            param.setEndcargoInfo(agvStorageTask.getWebCode());
            param.setWbCode(agvStorageTask.getWebCode());
            HikRsVo hikRsVo = HikApiUtils.genctnrBinTask(agvStorageTask.getAgvApiBaseUrl(), param);
            if (hikRsVo == null) {
                return ResponseData.error("接口调用错误");
            } else if (!"0".equals(hikRsVo.getCode()) && !hikRsVo.getMessage().contains("不需要下发任务")) {
                return ResponseData.error(hikRsVo.getMessage());
            }
            AgvStorageTaskParam updateAgvStorageTask = new AgvStorageTaskParam();
            updateAgvStorageTask.setId(agvStorageTask.getId());
            updateAgvStorageTask.setStat("20");
            agvStorageTaskService.update(updateAgvStorageTask);
        } else if ("TUSK".equals(agvStorageTask.getAgvTyp())) {
            CreateSortParam param = new CreateSortParam();
            param.setTaskId(agvStorageTask.getTaskNo());
            //取货点
            param.getTargetActions().add(TargetActionsVo.builder()
                    .target(agvStorageTask.getWebCode())
                    .action("PUT")
                    .build());
            TuskRsVo tuskRs = TustApiUtils.createSortTask(agvStorageTask.getAgvApiBaseUrl(), param);
            if (tuskRs == null) {
                return ResponseData.error("接口调用错误");
            } else if (tuskRs.getCode() != 200) {
                return ResponseData.error(tuskRs.getMsg());
            }
        }

        //修改拣货单状态
        HxStorageOutDetailedParam hxStorageOutDetailedParam = new HxStorageOutDetailedParam();
        hxStorageOutDetailedParam.setStorageNumber(agvStorageTask.getStorageNumber());
        return this.agvCompleteStorage(hxStorageOutDetailedParam);
    }

    @Transactional(rollbackFor = Exception.class, timeout = 180)
    public ResponseData agvJhUser(String agvStorageTaskId, String jhUser) {
        //根据明细ID中的agv任务ID获取AGV拣货任务信息
        AgvStorageTask agvStorageTask = agvStorageTaskService.getById(agvStorageTaskId);
        if (agvStorageTask == null) {
            return ResponseData.error("AGV拣货任务不存在，无法执行该操作");
        }
        User byAccount = this.userService.getByAccount(jhUser);
        if (byAccount == null) {
            return ResponseData.error(jhUser + "账号不存在！");
        }
        //修改拣选人
        this.hxStorageOutService.lambdaUpdate()
                .eq(HxStorageOut::getStorageNumber, agvStorageTask.getStorageNumber())
                .set(HxStorageOut::getStorageUser, jhUser)
                .set(HxStorageOut::getStorageUserName, byAccount.getName())
                .update();
        return ResponseData.success();
    }

    /**
     * AGV拣货完成
     *
     * @param hxStorageOutDetailedParam
     * @return
     */
    @Transactional(rollbackFor = Exception.class, timeout = 180)
    public ResponseData agvCompleteStorage(HxStorageOutDetailedParam hxStorageOutDetailedParam) {
        User user = userAop.getUser();
        String stockPort = "";
        try {
            HxStorageOutParam storageOutParam = new HxStorageOutParam();
            storageOutParam.setStorageNumber(hxStorageOutDetailedParam.getStorageNumber());
            HxStorageOutResult storageOutResult = this.findSumBySpec(storageOutParam);
            if (storageOutResult == null || !storageOutResult.getStorageState().equals("拣货中")) {
                return ResponseData.error("拣货任务不存在或已拣货");
            }
            if (ToolUtil.isEmpty(storageOutResult.getStockPort())) {
                return ResponseData.error("未分配集货口");
            }
            stockPort = storageOutResult.getStockPort();

            BasicCustomer basicCustomer = basicCustomerService.getById(storageOutResult.getCustomerId());

            if (ToolUtil.isNotEmpty(basicCustomer.getNeedCheck()) && basicCustomer.getNeedCheck().equals("1")) {//如果质检
                storageOutParam.setStorageState("待复核");
                storageOutParam.setId(storageOutResult.getId());
                storageOutParam.setStorageCompleteTime(new Date());
                this.update(storageOutParam);
            } else {
                storageOutParam.setStorageState("已完成");
                storageOutParam.setId(storageOutResult.getId());
                storageOutParam.setStorageCompleteTime(new Date());
                this.update(storageOutParam);
            }

            HxCollectionLocationParam hxCollectionLocationParam = new HxCollectionLocationParam();
            hxCollectionLocationParam.setStatus("已占用");
            hxCollectionLocationParam.setTrayNumber(storageOutResult.getTrayNumber());
            hxCollectionLocationParam.setStockPort(stockPort);
            hxCollectionLocationParam.setDeptId(user.getDeptId());
            hxCollectionLocationParam.setOperateId(user.getOperateId());
            hxCollectionLocationService.deliveryTray(hxCollectionLocationParam);

            if (ToolUtil.isEmpty(storageOutResult.getScattered())) {
                hxStorageOutDetailedService.updaterealNumBySpec(hxStorageOutDetailedParam);//更新实拣数量 = 应拣数量(应急可以取消整箱区扫码拣选)
            }
            //扣减库存
            HxStorageOutDetailedParam hxStorageOutDetailedParamf = new HxStorageOutDetailedParam();
            hxStorageOutDetailedParamf.setStorageNumber(hxStorageOutDetailedParam.getStorageNumber());
            List<HxStorageOutDetailedResult> dlist = hxStorageOutDetailedService.findListBySpec(hxStorageOutDetailedParamf);
            BigDecimal as = new BigDecimal("0");
            BigDecimal shi = new BigDecimal("10");
            List<HxStorageStock> sadd = new ArrayList<HxStorageStock>();
            for (HxStorageOutDetailedResult d : dlist) {
                HxStorageStockParam subHxStorageStockParam = new HxStorageStockParam();
                if (d.getStockId() != null) {
                    subHxStorageStockParam.setId(Integer.parseInt(d.getStockId().toString()));
                }
                subHxStorageStockParam.setStockState("正常");
                subHxStorageStockParam.setWarehouseId(storageOutResult.getSetWarehouseId());
                subHxStorageStockParam.setPositionId(d.getPositionId());
                subHxStorageStockParam.setPositionType("拣货位");
                subHxStorageStockParam.setGoodsId(d.getGoodsId());
                List<HxStorageStockResult> subs = hxStorageStockService.findsubListBySpec(subHxStorageStockParam);
                BigDecimal rate = new BigDecimal(d.getRate());//出库换算率
                if (ToolUtil.isEmpty(d.getRealNum())) {
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); //手动回滚
                    return ResponseData.error(d.getGoodsName() + ",未拣货!");
                }
                BigDecimal realNum = new BigDecimal(d.getRealNum());//实拣数量
                //实拣基本数量
                BigDecimal realNumJiben = realNum.multiply(new BigDecimal(d.getRate()));
                for (HxStorageStockResult obj : subs) {
                    BigDecimal _kcRate = new BigDecimal(obj.getKcRate());
                    //修改拣货明细计量
                    if (ToolUtil.isEmpty(d.getDetailedDate())) {
                        d.setDetailedDate(obj.getDetailedDate());
                        d.setDaoqiDate(obj.getExpirationDate());
                        HxStorageOutDetailedParam sdp = new HxStorageOutDetailedParam();
                        sdp.setId(d.getId());
                        sdp.setDetailedDate(obj.getDetailedDate());
                        sdp.setDaoqiDate(obj.getExpirationDate());
                        hxStorageOutDetailedService.update(sdp);
                    }
                    //库存数量大于拣货数量 库存计量需要拆开
                    if (obj.getJibenNum().compareTo(realNumJiben) == 1) {
                        //基本单位对应的体积重量
                        BigDecimal goodsVolume = new BigDecimal(obj.getStockVolume()).divide(obj.getJibenNum(), 10, BigDecimal.ROUND_HALF_DOWN);
                        BigDecimal goodsWeight = new BigDecimal(obj.getStockWeight()).divide(obj.getJibenNum(), 10, BigDecimal.ROUND_HALF_DOWN);
                        ;
                        BigDecimal goodsPrice = new BigDecimal(obj.getStockMoney()).divide(obj.getJibenNum(), 10, BigDecimal.ROUND_HALF_DOWN);
                        ;
                        //剩余库存
                        BigDecimal sykc = obj.getJibenNum().subtract(realNumJiben);
                        //修改扣除后的库存计量
                        HxStorageStockParam updateHxStorageStockParam = new HxStorageStockParam();
                        updateHxStorageStockParam.setId(obj.getId());
                        updateHxStorageStockParam.setStockVolume(sykc.multiply(goodsVolume).setScale(4, BigDecimal.ROUND_HALF_DOWN).toString());
                        updateHxStorageStockParam.setStockWeight(sykc.multiply(goodsWeight).setScale(3, BigDecimal.ROUND_HALF_DOWN).toString());
                        updateHxStorageStockParam.setStockMoney(sykc.multiply(goodsPrice).setScale(3, BigDecimal.ROUND_HALF_DOWN).toString());
                        updateHxStorageStockParam.setKcNum(String.valueOf(sykc.divide(_kcRate, 3, BigDecimal.ROUND_HALF_DOWN)));
                        updateHxStorageStockParam.setJibenNum(sykc);
                        hxStorageStockService.update(updateHxStorageStockParam);
                        //添加集货区库存
                        HxStorageStock updateHxStorageStockParamadd = new HxStorageStock();
                        ToolUtil.copyProperties(obj, updateHxStorageStockParamadd);
                        updateHxStorageStockParamadd.setId(null);
                        updateHxStorageStockParamadd.setStorageNumber(storageOutResult.getStorageNumber());
                        updateHxStorageStockParamadd.setStockState("集货");
                        updateHxStorageStockParamadd.setAreaId(null);
                        updateHxStorageStockParamadd.setAreaNumber(null);
                        updateHxStorageStockParamadd.setAreaName("集货区");
//                        updateHxStorageStockParamadd.setPositionId(null);
                        updateHxStorageStockParamadd.setPositionType("集货位");
                        updateHxStorageStockParamadd.setPositionNumber(storageOutResult.getStockPort());
                        updateHxStorageStockParamadd.setTrayNumber(storageOutResult.getTrayNumber());
                        updateHxStorageStockParamadd.setStockVolume(realNumJiben.multiply(goodsVolume).setScale(4, BigDecimal.ROUND_HALF_DOWN).toString());
                        updateHxStorageStockParamadd.setStockWeight(realNumJiben.multiply(goodsWeight).setScale(3, BigDecimal.ROUND_HALF_DOWN).toString());
                        updateHxStorageStockParamadd.setStockMoney(realNumJiben.multiply(goodsPrice).setScale(3, BigDecimal.ROUND_HALF_DOWN).toString());
                        updateHxStorageStockParamadd.setKcNum(String.valueOf(realNumJiben.divide(_kcRate, 3, BigDecimal.ROUND_HALF_DOWN)));
                        updateHxStorageStockParamadd.setJibenNum(realNumJiben);
                        sadd.add(updateHxStorageStockParamadd);
                        realNumJiben = new BigDecimal(0);
                    } else {
                        hxStorageStockService.lambdaUpdate()
                                .eq(HxStorageStock::getId, obj.getId())
                                .set(HxStorageStock::getStorageNumber, storageOutResult.getStorageNumber())
                                .set(HxStorageStock::getStockState, "集货")
                                .set(HxStorageStock::getAreaId, null)
                                .set(HxStorageStock::getAreaNumber, null)
                                .set(HxStorageStock::getAreaName, "集货区")
//                                .set(HxStorageStock::getPositionId, null)
                                .set(HxStorageStock::getPositionType, "集货位")
                                .set(HxStorageStock::getPositionNumber, storageOutResult.getStockPort())
                                .set(HxStorageStock::getTrayNumber, storageOutResult.getTrayNumber())
                                .update();
                        realNumJiben = realNumJiben.subtract(obj.getJibenNum());
                    }
                    //拣货数量为0时，退出循环
                    if (realNumJiben.compareTo(as) == 0) {
                        break;
                    }
                }
                //库存循环完，还有未扣库存，说明货物不足
                if (realNumJiben.compareTo(as) == 1) {
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); //手动回滚
                    return ResponseData.error(d.getGoodsName() + ",拣货位货物不足!");
                }
            }
            if (sadd.size() > 0) {
                hxStorageStockService.saveBatch(sadd);
            }
            // 不质检 直接生成货运订单
            if (ToolUtil.isEmpty(basicCustomer.getNeedCheck()) || basicCustomer.getNeedCheck().equals("2")) {//如果不质检
                //新增货运订单
                if (ToolUtil.isNotEmpty(basicCustomer.getGenerateTms())) {
                    if (basicCustomer.getGenerateTms().equals("1")) {
                        List<OrderTransportDetailedParam> transportdList = new ArrayList<OrderTransportDetailedParam>();//批量保存的 货运订单list
                        BasicOperate basicOperate = basicOperateService.getById(basicCustomer.getCustomerOperateId());
                        String trayCode = getOperateIdOrderPrefix(user);
                        String name = "零脉";

                        OrderTransportParam addp = new OrderTransportParam();
                        addp.setOperateId(Long.parseLong(basicCustomer.getCustomerOperateId().toString()));//分公司id
                        addp.setOperateName(basicOperate.getOperateName());//公司名称
                        addp.setCustomerOrder(storageOutResult.getTrayNumber() + "_" + storageOutResult.getStorageNumber());
                        addp.setTransportNumber(trayCode + "HY" + cn.stylefeng.guns.core.util.DateUtil.getDatesBch() + DateUtil.getRandomNumber());
                        addp.setOrderNumber(storageOutResult.getStorageNumber());
                        addp.setDemolition(storageOutResult.getScattered());
                        addp.setLmOrderType(storageOutResult.getOrderType());
                        addp.setLmAssociationOrder(storageOutResult.getAssociationOrder());
                        if (ToolUtil.isNotEmpty(storageOutResult.getPieceNumber())) {
                            addp.setPieceNumber(storageOutResult.getPieceNumber());
                        } else {
                            if (ToolUtil.isNotEmpty(storageOutResult.getScattered())) {
                                BigDecimal realNum = new BigDecimal(storageOutResult.getRealNum());
                                if (realNum.compareTo(as) == 1) {
                                    BigDecimal pieceNumberbig = realNum.divide(shi, 3, BigDecimal.ROUND_HALF_DOWN);
                                    addp.setPieceNumber(pieceNumberbig + "");
                                } else {
                                    addp.setPieceNumber("0");
                                }
                            } else {
                                addp.setPieceNumber("0");
                            }
                        }
                        addp.setOrderSource("零脉");
                        addp.setCustomerId(Long.parseLong(basicCustomer.getId().toString()));//客户id
                        addp.setCustomerName(basicCustomer.getCustomerName());//客户名称
                        addp.setUndertime(DateUtil2.getDateS());//下单时间
                        addp.setSetMentiontime(storageOutResult.getPeisongTime());//发货日期

                        addp.setXlbSetUnitId(storageOutResult.getXlbSetUnitId());
                        addp.setSetUnit(storageOutResult.getSetUnit());//装货单位
                        addp.setSetUnitId(storageOutResult.getSetUnitId());//装货单位id
                        addp.setXlbSetWarehouse(storageOutResult.getSetWarehouse());
                        addp.setXlbSetWarehouseId(storageOutResult.getXlbSetWarehouseId());
                        addp.setXlbClientId(storageOutResult.getXlbClientId());
                        addp.setGetUnit(storageOutResult.getGetUnit());
                        addp.setGetUnitId(storageOutResult.getGetUnitId());
                        addp.setStockPort(storageOutResult.getStockPort());//备货口

                        toDealWith4(addp);//处理单位和地址

                        addp.setDeptId(user.getDeptId());
                        addp.setDeliverId(user.getDeliverId());
                        addp.setCreateName(name);
                        addp.setCreateTime(new Date());
                        addp.setGoodsNum(storageOutResult.getGoodsNum());

                        addp.setTooNum("0");
                        addp.setTooVolume("0");
                        addp.setTstate("待调");
                        BigDecimal TotalNum = new BigDecimal("0");//货物单总数
                        BigDecimal TotalVolume = new BigDecimal("0");//货物单总体积
                        //货品信息
                        hxStorageOutDetailedParamf = new HxStorageOutDetailedParam();
                        hxStorageOutDetailedParamf.setStorageNumber(hxStorageOutDetailedParam.getStorageNumber());
                        List<HxStorageOutDetailedResult> hxStorageOutDetaileds = hxStorageOutDetailedService.findListBySpec(hxStorageOutDetailedParamf);
                        Map<String, HxStorageOutDetailedResult> hxBasicGoodsMap = new HashedMap();
                        for (HxStorageOutDetailedResult obj : hxStorageOutDetaileds) {
                            hxBasicGoodsMap.put(obj.getGoodsId().toString(), obj);
                        }
                        //根据拣货单号获取库存列表
                        HxStorageStockParam hxStorageStockParam = new HxStorageStockParam();
                        hxStorageStockParam.setStorageNumber(storageOutResult.getStorageNumber());
                        hxStorageStockParam.setWarehouseId(storageOutResult.getSetWarehouseId());
                        List<HxStorageStockResult> hxStorageStockStorageNumbers = hxStorageStockService.findListByStorageNumber1(hxStorageStockParam);
                        //库位信息
                        List<BasicPosition> basicPositions = basicPositionService.lambdaQuery()
                                .eq(BasicPosition::getWarehouseId, storageOutResult.getSetWarehouseId())
                                .eq(BasicPosition::getPositionType, "拣货位")
                                .list();
                        Map<String, BasicPosition> basicPositionMap = new HashedMap();
                        for (BasicPosition obj : basicPositions) {
                            basicPositionMap.put(obj.getId().toString(), obj);
                        }

                        for (HxStorageStockResult obj : hxStorageStockStorageNumbers) {
                            //新增货运明细
                            OrderTransportDetailedParam outTranDetailed = new OrderTransportDetailedParam();
                            outTranDetailed.setTransportNumber(addp.getTransportNumber());
                            if (ToolUtil.isNotEmpty(obj.getPositionId()) && basicPositionMap.get(obj.getPositionId().toString()) != null) {
                                outTranDetailed.setXlbPositionId(basicPositionMap.get(obj.getPositionId().toString()).getPositionXlbId());
                                outTranDetailed.setPositionNumber(basicPositionMap.get(obj.getPositionId().toString()).getPositionNumber());
                            }
                            outTranDetailed.setPositionId(obj.getPositionId());

                            outTranDetailed.setGoodsVolume(obj.getGoodsVolume());
                            outTranDetailed.setTransportPutvolume(obj.getStockVolume());
                            outTranDetailed.setGoodsWeight(obj.getGoodsWeight());
                            outTranDetailed.setTransportWeight(obj.getStockWeight());
                            outTranDetailed.setUnitprice(hxBasicGoodsMap.get(obj.getGoodsId().toString()).getGoodsPrice());
                            //金额=单价/rate*基本数量
                            if (ToolUtil.isNotEmpty(hxBasicGoodsMap.get(obj.getGoodsId().toString()).getGoodsPrice()) && ToolUtil.isNotEmpty(hxBasicGoodsMap.get(obj.getGoodsId().toString()).getRate())) {
                                BigDecimal transportMoney = obj.getJibenNum().multiply(new BigDecimal(hxBasicGoodsMap.get(obj.getGoodsId().toString()).getGoodsPrice())).divide(new BigDecimal(hxBasicGoodsMap.get(obj.getGoodsId().toString()).getRate()), 3, BigDecimal.ROUND_HALF_DOWN).setScale(3, BigDecimal.ROUND_HALF_DOWN);
                                outTranDetailed.setTransportMoney(transportMoney.toString());
                            }


                            outTranDetailed.setXlbGoodsId(hxBasicGoodsMap.get(obj.getGoodsId().toString()).getXlbGoodsId());
                            outTranDetailed.setGoodId(obj.getGoodsId());
                            outTranDetailed.setGoodsName(obj.getGoodsName());
                            outTranDetailed.setGoodsNumber(obj.getGoodsNumber());
                            outTranDetailed.setGoodsPcode69(obj.getGoodsPcode69());
                            outTranDetailed.setGoodsUnit(obj.getKcUnit());
                            outTranDetailed.setGoodsSpecs(obj.getGoodsSpecs());

                            outTranDetailed.setJibenUnit(obj.getJibenUnit());
                            outTranDetailed.setJibenNum(String.valueOf(obj.getJibenNum()));
                            outTranDetailed.setBalenum(obj.getKcNum());
                            outTranDetailed.setNum(obj.getKcNum());
                            outTranDetailed.setRate(obj.getKcRate());

                            outTranDetailed.setDetailedDate(obj.getDetailedDate());
                            outTranDetailed.setDaoqiDate(obj.getExpirationDate());

                            outTranDetailed.setNotnum(outTranDetailed.getNum());
                            outTranDetailed.setNotvolume(outTranDetailed.getTransportPutvolume());
                            BigDecimal num = new BigDecimal(outTranDetailed.getNum());
                            if (num.compareTo(as) == 1) {
                                transportdList.add(outTranDetailed);
                            } else {
                                continue;
                            }

                            BigDecimal transportPutvolume = new BigDecimal(outTranDetailed.getTransportPutvolume());
                            BigDecimal nTotalNum = TotalNum.add(num);
                            TotalNum = nTotalNum;
                            BigDecimal nTotalVolume = TotalVolume.add(transportPutvolume);
                            TotalVolume = nTotalVolume;
                        }
                        addp.setTotalNum(TotalNum.setScale(3, BigDecimal.ROUND_HALF_DOWN).toString());
                        addp.setTotalVolume(TotalVolume.setScale(4, BigDecimal.ROUND_HALF_DOWN).toString());
                        if (TotalNum.compareTo(as) == 1) {
                            orderTransportService.add(addp);
                            if (transportdList.size() > 0) {
                                this.orderTransportDetailedService.saveBatchList(transportdList);
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); //手动回滚
            e.printStackTrace();
        }
        return ResponseData.success("备货口：" + stockPort);
    }

    /**
     * AGV拣货完成
     *
     * @param hxStorageOutDetailedParam
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class, timeout = 300)
    public ResponseData dpsCompleteStorage(HxStorageOutDetailedParam hxStorageOutDetailedParam) throws Exception {
        User user = userService.getByAccount("LYDPS");
        String stockPort = "";
        try {
            HxStorageOutParam storageOutParam = new HxStorageOutParam();
            storageOutParam.setStorageNumber(hxStorageOutDetailedParam.getStorageNumber());
            HxStorageOutResult storageOutResult = this.findSumBySpec(storageOutParam);
            if (storageOutResult == null || !storageOutResult.getStorageState().equals("拣货中")) {
                return ResponseData.error("拣货任务不存在或已拣货");
            }
            if (ToolUtil.isEmpty(storageOutResult.getStockPort())) {
                return ResponseData.error("未分配集货口");
            }
            stockPort = storageOutResult.getStockPort();

            BasicCustomer basicCustomer = basicCustomerService.getById(storageOutResult.getCustomerId());

            if (ToolUtil.isNotEmpty(basicCustomer.getNeedCheck()) && basicCustomer.getNeedCheck().equals("1")) {//如果质检
                storageOutParam.setStorageState("待复核");
                storageOutParam.setId(storageOutResult.getId());
                storageOutParam.setStorageCompleteTime(new Date());
                this.update(storageOutParam);
            } else {
                storageOutParam.setStorageState("已完成");
                storageOutParam.setId(storageOutResult.getId());
                storageOutParam.setStorageCompleteTime(new Date());
                this.update(storageOutParam);
            }

            HxCollectionLocationParam hxCollectionLocationParam = new HxCollectionLocationParam();
            hxCollectionLocationParam.setStatus("已占用");
            hxCollectionLocationParam.setTrayNumber(storageOutResult.getTrayNumber());
            hxCollectionLocationParam.setStockPort(stockPort);
            hxCollectionLocationParam.setDeptId(user.getDeptId());
            hxCollectionLocationParam.setOperateId(user.getOperateId());
            hxCollectionLocationService.deliveryTray(hxCollectionLocationParam);

            if (ToolUtil.isEmpty(storageOutResult.getScattered())) {
                hxStorageOutDetailedService.updaterealNumBySpec(hxStorageOutDetailedParam);//更新实拣数量 = 应拣数量(应急可以取消整箱区扫码拣选)
            }
            //扣减库存
            HxStorageOutDetailedParam hxStorageOutDetailedParamf = new HxStorageOutDetailedParam();
            hxStorageOutDetailedParamf.setStorageNumber(hxStorageOutDetailedParam.getStorageNumber());
            List<HxStorageOutDetailedResult> dlist = hxStorageOutDetailedService.findListBySpec(hxStorageOutDetailedParamf);
            BigDecimal as = new BigDecimal("0");
            BigDecimal shi = new BigDecimal("10");
            List<HxStorageStock> sadd = new ArrayList<HxStorageStock>();
            for (HxStorageOutDetailedResult d : dlist) {
                HxStorageStockParam subHxStorageStockParam = new HxStorageStockParam();
                if (d.getStockId() != null) {
                    subHxStorageStockParam.setId(Integer.parseInt(d.getStockId().toString()));
                }
                subHxStorageStockParam.setStockState("正常");
                subHxStorageStockParam.setWarehouseId(storageOutResult.getSetWarehouseId());
                subHxStorageStockParam.setPositionId(d.getPositionId());
                subHxStorageStockParam.setPositionType("拣货位");
                subHxStorageStockParam.setGoodsId(d.getGoodsId());
                List<HxStorageStockResult> subs = hxStorageStockService.findsubListBySpec(subHxStorageStockParam);
                BigDecimal rate = new BigDecimal(d.getRate());//出库换算率
                if (ToolUtil.isEmpty(d.getRealNum())) {
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); //手动回滚
                    return ResponseData.error(d.getGoodsName() + ",未拣货!");
                }
                BigDecimal realNum = new BigDecimal(d.getRealNum());//实拣数量
                //实拣基本数量
                BigDecimal realNumJiben = realNum.multiply(new BigDecimal(d.getRate()));
                for (HxStorageStockResult obj : subs) {
                    BigDecimal _kcRate = new BigDecimal(obj.getKcRate());
                    //修改拣货明细计量
                    if (ToolUtil.isEmpty(d.getDetailedDate())) {
                        d.setDetailedDate(obj.getDetailedDate());
                        d.setDaoqiDate(obj.getExpirationDate());
                        HxStorageOutDetailedParam sdp = new HxStorageOutDetailedParam();
                        sdp.setId(d.getId());
                        sdp.setDetailedDate(obj.getDetailedDate());
                        sdp.setDaoqiDate(obj.getExpirationDate());
                        hxStorageOutDetailedService.update(sdp);
                    }
                    //库存数量大于拣货数量 库存计量需要拆开
                    if (obj.getJibenNum().compareTo(realNumJiben) == 1) {
                        //基本单位对应的体积重量
                        BigDecimal goodsVolume = new BigDecimal(obj.getStockVolume()).divide(obj.getJibenNum(), 10, BigDecimal.ROUND_HALF_DOWN);
                        BigDecimal goodsWeight = new BigDecimal(obj.getStockWeight()).divide(obj.getJibenNum(), 10, BigDecimal.ROUND_HALF_DOWN);
                        ;
                        BigDecimal goodsPrice = new BigDecimal(obj.getStockMoney()).divide(obj.getJibenNum(), 10, BigDecimal.ROUND_HALF_DOWN);
                        ;
                        //剩余库存
                        BigDecimal sykc = obj.getJibenNum().subtract(realNumJiben);
                        //修改扣除后的库存计量
                        HxStorageStockParam updateHxStorageStockParam = new HxStorageStockParam();
                        updateHxStorageStockParam.setId(obj.getId());
                        updateHxStorageStockParam.setStockVolume(sykc.multiply(goodsVolume).setScale(4, BigDecimal.ROUND_HALF_DOWN).toString());
                        updateHxStorageStockParam.setStockWeight(sykc.multiply(goodsWeight).setScale(3, BigDecimal.ROUND_HALF_DOWN).toString());
                        updateHxStorageStockParam.setStockMoney(sykc.multiply(goodsPrice).setScale(3, BigDecimal.ROUND_HALF_DOWN).toString());
                        updateHxStorageStockParam.setKcNum(String.valueOf(sykc.divide(_kcRate, 3, BigDecimal.ROUND_HALF_DOWN)));
                        updateHxStorageStockParam.setJibenNum(sykc);
                        hxStorageStockService.update(updateHxStorageStockParam);
                        //添加集货区库存
                        HxStorageStock updateHxStorageStockParamadd = new HxStorageStock();
                        ToolUtil.copyProperties(obj, updateHxStorageStockParamadd);
                        updateHxStorageStockParamadd.setId(null);
                        updateHxStorageStockParamadd.setStorageNumber(storageOutResult.getStorageNumber());
                        updateHxStorageStockParamadd.setStockState("集货");
                        updateHxStorageStockParamadd.setAreaId(null);
                        updateHxStorageStockParamadd.setAreaNumber(null);
                        updateHxStorageStockParamadd.setAreaName("集货区");
//                        updateHxStorageStockParamadd.setPositionId(null);
                        updateHxStorageStockParamadd.setPositionType("集货位");
                        updateHxStorageStockParamadd.setPositionNumber(storageOutResult.getStockPort());
                        updateHxStorageStockParamadd.setTrayNumber(storageOutResult.getTrayNumber());
                        updateHxStorageStockParamadd.setStockVolume(realNumJiben.multiply(goodsVolume).setScale(4, BigDecimal.ROUND_HALF_DOWN).toString());
                        updateHxStorageStockParamadd.setStockWeight(realNumJiben.multiply(goodsWeight).setScale(3, BigDecimal.ROUND_HALF_DOWN).toString());
                        updateHxStorageStockParamadd.setStockMoney(realNumJiben.multiply(goodsPrice).setScale(3, BigDecimal.ROUND_HALF_DOWN).toString());
                        updateHxStorageStockParamadd.setKcNum(String.valueOf(realNumJiben.divide(_kcRate, 3, BigDecimal.ROUND_HALF_DOWN)));
                        updateHxStorageStockParamadd.setJibenNum(realNumJiben);
                        sadd.add(updateHxStorageStockParamadd);
                        realNumJiben = new BigDecimal(0);
                    } else {
                        hxStorageStockService.lambdaUpdate()
                                .eq(HxStorageStock::getId, obj.getId())
                                .set(HxStorageStock::getStorageNumber, storageOutResult.getStorageNumber())
                                .set(HxStorageStock::getStockState, "集货")
                                .set(HxStorageStock::getAreaId, null)
                                .set(HxStorageStock::getAreaNumber, null)
                                .set(HxStorageStock::getAreaName, "集货区")
//                                .set(HxStorageStock::getPositionId, null)
                                .set(HxStorageStock::getPositionType, "集货位")
                                .set(HxStorageStock::getPositionNumber, storageOutResult.getStockPort())
                                .set(HxStorageStock::getTrayNumber, storageOutResult.getTrayNumber())
                                .update();
                        realNumJiben = realNumJiben.subtract(obj.getJibenNum());
                    }
                    //拣货数量为0时，退出循环
                    if (realNumJiben.compareTo(as) == 0) {
                        break;
                    }
                }
                //库存循环完，还有未扣库存，说明货物不足
                if (realNumJiben.compareTo(as) == 1) {
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); //手动回滚
                    return ResponseData.error(d.getGoodsName() + ",拣货位货物不足!");
                }
            }

            if (sadd.size() > 0 && "1".equals(basicCustomer.getGenerateTms())) {
                hxStorageStockService.saveBatch(sadd);
            }

            // 不质检 直接生成货运订单
            if (ToolUtil.isEmpty(basicCustomer.getNeedCheck()) || basicCustomer.getNeedCheck().equals("2")) {//如果不质检
                //新增货运订单
                if (ToolUtil.isNotEmpty(basicCustomer.getGenerateTms())) {
                    if (basicCustomer.getGenerateTms().equals("1")) {
                        List<OrderTransportDetailedParam> transportdList = new ArrayList<OrderTransportDetailedParam>();//批量保存的 货运订单list
                        BasicOperate basicOperate = basicOperateService.getById(basicCustomer.getCustomerOperateId());
                        String trayCode = getOperateIdOrderPrefix(user);
                        String name = "零脉";

                        OrderTransportParam addp = new OrderTransportParam();
                        addp.setOperateId(Long.parseLong(basicCustomer.getCustomerOperateId().toString()));//分公司id
                        addp.setOperateName(basicOperate.getOperateName());//公司名称
                        addp.setCustomerOrder(storageOutResult.getTrayNumber() + "_" + storageOutResult.getStorageNumber());
                        addp.setTransportNumber(trayCode + "HY" + cn.stylefeng.guns.core.util.DateUtil.getDatesBch() + DateUtil.getRandomNumber());
                        addp.setOrderNumber(storageOutResult.getStorageNumber());
                        addp.setDemolition(storageOutResult.getScattered());
                        addp.setLmOrderType(storageOutResult.getOrderType());
                        addp.setLmAssociationOrder(storageOutResult.getAssociationOrder());
                        if (ToolUtil.isNotEmpty(storageOutResult.getPieceNumber())) {
                            addp.setPieceNumber(storageOutResult.getPieceNumber());
                        } else {
                            if (ToolUtil.isNotEmpty(storageOutResult.getScattered())) {
                                BigDecimal realNum = new BigDecimal(storageOutResult.getRealNum());
                                if (realNum.compareTo(as) == 1) {
                                    BigDecimal pieceNumberbig = realNum.divide(shi, 3, BigDecimal.ROUND_HALF_DOWN);
                                    addp.setPieceNumber(pieceNumberbig + "");
                                } else {
                                    addp.setPieceNumber("0");
                                }
                            } else {
                                addp.setPieceNumber("0");
                            }
                        }
                        addp.setOrderSource("零脉");
                        addp.setCustomerId(Long.parseLong(basicCustomer.getId().toString()));//客户id
                        addp.setCustomerName(basicCustomer.getCustomerName());//客户名称
                        addp.setUndertime(DateUtil2.getDateS());//下单时间
                        addp.setSetMentiontime(storageOutResult.getPeisongTime());//发货日期

                        addp.setXlbSetUnitId(storageOutResult.getXlbSetUnitId());
                        addp.setSetUnit(storageOutResult.getSetUnit());//装货单位
                        addp.setSetUnitId(storageOutResult.getSetUnitId());//装货单位id
                        addp.setXlbSetWarehouse(storageOutResult.getSetWarehouse());
                        addp.setXlbSetWarehouseId(storageOutResult.getXlbSetWarehouseId());
                        addp.setXlbClientId(storageOutResult.getXlbClientId());
                        addp.setGetUnit(storageOutResult.getGetUnit());
                        addp.setGetUnitId(storageOutResult.getGetUnitId());
                        addp.setStockPort(storageOutResult.getStockPort());//备货口

                        toDealWith4(addp);//处理单位和地址

                        addp.setDeptId(user.getDeptId());
                        addp.setDeliverId(user.getDeliverId());
                        addp.setCreateName(name);
                        addp.setCreateTime(new Date());
                        addp.setGoodsNum(storageOutResult.getGoodsNum());

                        addp.setTooNum("0");
                        addp.setTooVolume("0");
                        addp.setTstate("待调");
                        BigDecimal TotalNum = new BigDecimal("0");//货物单总数
                        BigDecimal TotalVolume = new BigDecimal("0");//货物单总体积
                        //货品信息
                        hxStorageOutDetailedParamf = new HxStorageOutDetailedParam();
                        hxStorageOutDetailedParamf.setStorageNumber(hxStorageOutDetailedParam.getStorageNumber());
                        List<HxStorageOutDetailedResult> hxStorageOutDetaileds = hxStorageOutDetailedService.findListBySpec(hxStorageOutDetailedParamf);
                        Map<String, HxStorageOutDetailedResult> hxBasicGoodsMap = new HashedMap();
                        for (HxStorageOutDetailedResult obj : hxStorageOutDetaileds) {
                            hxBasicGoodsMap.put(obj.getGoodsId().toString(), obj);
                        }
                        //根据拣货单号获取库存列表
                        HxStorageStockParam hxStorageStockParam = new HxStorageStockParam();
                        hxStorageStockParam.setStorageNumber(storageOutResult.getStorageNumber());
                        hxStorageStockParam.setWarehouseId(storageOutResult.getSetWarehouseId());
                        List<HxStorageStockResult> hxStorageStockStorageNumbers = hxStorageStockService.findListByStorageNumber1(hxStorageStockParam);
                        //库位信息
                        List<BasicPosition> basicPositions = basicPositionService.lambdaQuery()
                                .eq(BasicPosition::getWarehouseId, storageOutResult.getSetWarehouseId())
                                .eq(BasicPosition::getPositionType, "拣货位")
                                .list();
                        Map<String, BasicPosition> basicPositionMap = new HashedMap();
                        for (BasicPosition obj : basicPositions) {
                            basicPositionMap.put(obj.getId().toString(), obj);
                        }

                        for (HxStorageStockResult obj : hxStorageStockStorageNumbers) {
                            //新增货运明细
                            OrderTransportDetailedParam outTranDetailed = new OrderTransportDetailedParam();
                            outTranDetailed.setTransportNumber(addp.getTransportNumber());
                            if (ToolUtil.isNotEmpty(obj.getPositionId()) && basicPositionMap.get(obj.getPositionId().toString()) != null) {
                                outTranDetailed.setXlbPositionId(basicPositionMap.get(obj.getPositionId().toString()).getPositionXlbId());
                                outTranDetailed.setPositionNumber(basicPositionMap.get(obj.getPositionId().toString()).getPositionNumber());
                            }
                            outTranDetailed.setPositionId(obj.getPositionId());

                            outTranDetailed.setGoodsVolume(obj.getGoodsVolume());
                            outTranDetailed.setTransportPutvolume(obj.getStockVolume());
                            outTranDetailed.setGoodsWeight(obj.getGoodsWeight());
                            outTranDetailed.setTransportWeight(obj.getStockWeight());
                            outTranDetailed.setUnitprice(hxBasicGoodsMap.get(obj.getGoodsId().toString()).getGoodsPrice());
                            //金额=单价/rate*基本数量
                            if (ToolUtil.isNotEmpty(hxBasicGoodsMap.get(obj.getGoodsId().toString()).getGoodsPrice()) && ToolUtil.isNotEmpty(hxBasicGoodsMap.get(obj.getGoodsId().toString()).getRate())) {
                                BigDecimal transportMoney = obj.getJibenNum().multiply(new BigDecimal(hxBasicGoodsMap.get(obj.getGoodsId().toString()).getGoodsPrice())).divide(new BigDecimal(hxBasicGoodsMap.get(obj.getGoodsId().toString()).getRate()), 3, BigDecimal.ROUND_HALF_DOWN).setScale(3, BigDecimal.ROUND_HALF_DOWN);
                                outTranDetailed.setTransportMoney(transportMoney.toString());
                            }


                            outTranDetailed.setXlbGoodsId(hxBasicGoodsMap.get(obj.getGoodsId().toString()).getXlbGoodsId());
                            outTranDetailed.setGoodId(obj.getGoodsId());
                            outTranDetailed.setGoodsName(obj.getGoodsName());
                            outTranDetailed.setGoodsNumber(obj.getGoodsNumber());
                            outTranDetailed.setGoodsPcode69(obj.getGoodsPcode69());
                            outTranDetailed.setGoodsUnit(obj.getKcUnit());
                            outTranDetailed.setGoodsSpecs(obj.getGoodsSpecs());

                            outTranDetailed.setJibenUnit(obj.getJibenUnit());
                            outTranDetailed.setJibenNum(String.valueOf(obj.getJibenNum()));
                            outTranDetailed.setBalenum(obj.getKcNum());
                            outTranDetailed.setNum(obj.getKcNum());
                            outTranDetailed.setRate(obj.getKcRate());

                            outTranDetailed.setDetailedDate(obj.getDetailedDate());
                            outTranDetailed.setDaoqiDate(obj.getExpirationDate());

                            outTranDetailed.setNotnum(outTranDetailed.getNum());
                            outTranDetailed.setNotvolume(outTranDetailed.getTransportPutvolume());
                            BigDecimal num = new BigDecimal(outTranDetailed.getNum());
                            if (num.compareTo(as) == 1) {
                                transportdList.add(outTranDetailed);
                            } else {
                                continue;
                            }

                            BigDecimal transportPutvolume = new BigDecimal(outTranDetailed.getTransportPutvolume());
                            BigDecimal nTotalNum = TotalNum.add(num);
                            TotalNum = nTotalNum;
                            BigDecimal nTotalVolume = TotalVolume.add(transportPutvolume);
                            TotalVolume = nTotalVolume;
                        }
                        addp.setTotalNum(TotalNum.setScale(3, BigDecimal.ROUND_HALF_DOWN).toString());
                        addp.setTotalVolume(TotalVolume.setScale(4, BigDecimal.ROUND_HALF_DOWN).toString());
                        if (TotalNum.compareTo(as) == 1) {
                            orderTransportService.add(addp);
                            if (transportdList.size() > 0) {
                                this.orderTransportDetailedService.saveBatchList(transportdList);
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); //手动回滚
            throw new Exception(e);
        }
        return ResponseData.success("备货口：" + stockPort);
    }

    @Override
    public LayuiPageInfo findPageBySpec2(HxStorageOutParam param, String condition, Long operateId) {
        Page pageContext = getPageContext();
        IPage page = this.baseMapper.customPageList2(pageContext, param, condition, operateId);
        return LayuiPageFactory.createPageInfo(page);
    }

    @Override
    public boolean checkCustomerStorage(String storageNumber) {
        return this.baseMapper.checkCustomerStorage(storageNumber) == null ? false : true;
    }

    @Override
    public void updateSum(String storageNumber) {
        this.baseMapper.updateSum(storageNumber);
    }

    @Override
    @Transactional(rollbackFor = Exception.class, timeout = 60)
    public ResponseData agvDistribute(HxStorageOutDetailedParam hxStorageOutDetailedParam, String pickupPoint,
                                      Integer priority, User user) {
        ResponseData resdata = ResponseData.success();
        HxStorageOutParam storageOutParam = new HxStorageOutParam();
        storageOutParam.setStorageNumber(hxStorageOutDetailedParam.getStorageNumber());
        HxStorageOutResult storageOutResult = this.findSumBySpec(storageOutParam);

        if (storageOutResult == null || !storageOutResult.getStorageState().equals("拣货中")) {
            return ResponseData.error("拣货任务不存在或已拣货");
        }
        if (ToolUtil.isEmpty(storageOutResult.getStockPort())) {
            return ResponseData.error("未分配集货口");
        }

        //如果是拆托，把已经完成拣货的新创建一个单及明细
        if (ToolUtil.isNotEmpty(hxStorageOutDetailedParam.getIsCt()) && "1".equals(hxStorageOutDetailedParam.getIsCt()) && new BigDecimal(storageOutResult.getRealNum()).compareTo(new BigDecimal(storageOutResult.getOutNum())) != 0) {
            //根据拣货单号，获取最大的拣货单号
            HxStorageOut one = this.lambdaQuery()
                    .likeRight(HxStorageOut::getStorageNumber, hxStorageOutDetailedParam.getStorageNumber())
                    .orderByDesc(HxStorageOut::getStorageNumber)
                    .last("limit 1 ")
                    .one();
            //新增拣货单
            HxStorageOutParam add = new HxStorageOutParam();
            ToolUtil.copyProperties(one, add);

            String storageNumber = one.getStorageNumber();
            int idex = storageNumber.lastIndexOf("-");
            if (idex > 0) {
                String str1 = storageNumber.substring(0, idex);
                String str2 = storageNumber.substring(idex + 1);
                try {
                    int icnt = Integer.parseInt(str2);
                    icnt++;
                    storageNumber = str1 + "-" + icnt;
//                        add.setTrayNumber(one.getTrayNumber() + "-" + icnt);
                } catch (Exception e) {
                    storageNumber = storageNumber + "-1";
//                        add.setTrayNumber(one.getTrayNumber() + "-1");
                    e.printStackTrace();
                }
            } else {
                storageNumber = storageNumber + "-1";
//                    add.setTrayNumber(one.getTrayNumber() + "-1");
            }

            add.setId(null);
            add.setPrintNumb(null);
            add.setPrintNumbTime(null);
            add.setCreateTime(new Date());
            add.setCreateUserName(user.getName());
            add.setStorageNumber(storageNumber);
            //如果传入目标点，则根据目标点送达
            if (ToolUtil.isNotEmpty(hxStorageOutDetailedParam.getStockPort()) && !"人工处理".equals(hxStorageOutDetailedParam.getStockPort())) {
                add.setStockPort(hxStorageOutDetailedParam.getStockPort().replace("H", "").replaceAll("^0+", ""));
            }
            this.add(add);
            //修改明细对应的拣货单号
            hxStorageOutDetailedService.lambdaUpdate()
                    .eq(HxStorageOutDetailed::getStorageNumber, hxStorageOutDetailedParam.getStorageNumber())
                    .apply(" num+0 = real_num+0 ")
                    .set(HxStorageOutDetailed::getStorageNumber, storageNumber)
                    .update();
            //新增明细
            hxStorageOutDetailedService.addByStorageNumber(hxStorageOutDetailedParam.getStorageNumber(), storageNumber);
            //修改原拣货单数量
            List<HxStorageOutDetailedResult> hxStorageOutDetailedResults = hxStorageOutDetailedService.selectGoodSNumByStorageNumber(hxStorageOutDetailedParam.getStorageNumber());
            for (HxStorageOutDetailedResult obj : hxStorageOutDetailedResults) {
                String sql = "num = " + obj.getNum() + ",real_num=0,out_weight=goods_weight*" + obj.getNum() + ",out_volume=goods_volume*" + obj.getNum() + ",jiben_num=rate*" + obj.getNum() + ",out_money=goods_price*" + obj.getNum();
                hxStorageOutDetailedService.lambdaUpdate()
                        .eq(HxStorageOutDetailed::getId, obj.getId())
                        .setSql(sql)
                        .update();
            }
//                //修改拣货单的汇总数据
//                hxStorageOutService.updateSum(storageNumber);
//                //修改之前的拣货任务总数据
//                hxStorageOutService.updateSum(hxStorageOutDetailedParam.getStorageNumber());
            //重新完成拣货
            storageOutParam = new HxStorageOutParam();
            storageOutParam.setStorageNumber(storageNumber);
            storageOutResult = this.findSumBySpec(storageOutParam);
            hxStorageOutDetailedParam.setStorageNumber(storageNumber);
        } else {
            if (ToolUtil.isNotEmpty(hxStorageOutDetailedParam.getSumNum())) {
                BigDecimal sumNum = new BigDecimal(hxStorageOutDetailedParam.getSumNum());
                BigDecimal realNumd = new BigDecimal(storageOutResult.getRealNum());
                if (sumNum.compareTo(realNumd) != 0) {
                    return ResponseData.error("输入总数量与实拣不一致！");
                }
            }
        }
        //返回拣货编号
//            resdata = ResponseData.success(hxStorageOutDetailedParam.getStorageNumber());
        BasicCustomer basicCustomer = basicCustomerService.getById(storageOutResult.getCustomerId());

        if (ToolUtil.isNotEmpty(basicCustomer.getNeedCheck()) && basicCustomer.getNeedCheck().equals("1")) {//如果质检
            storageOutParam.setStorageState("待复核");
            storageOutParam.setId(storageOutResult.getId());
            storageOutParam.setStorageCompleteTime(new Date());
            this.update(storageOutParam);
        } else {
            storageOutParam.setStorageState("已完成");
            storageOutParam.setId(storageOutResult.getId());
            storageOutParam.setStorageCompleteTime(new Date());
            this.update(storageOutParam);
        }

        HxCollectionLocationParam hxCollectionLocationParam = new HxCollectionLocationParam();
        hxCollectionLocationParam.setStatus("已占用");
        hxCollectionLocationParam.setTrayNumber(storageOutResult.getTrayNumber());
        hxCollectionLocationParam.setStockPort(storageOutResult.getStockPort());
        hxCollectionLocationParam.setDeptId(user.getDeptId());
        hxCollectionLocationParam.setOperateId(user.getOperateId());
        hxCollectionLocationService.deliveryTray(hxCollectionLocationParam);

        if (ToolUtil.isEmpty(basicCustomer.getBoxPickMode()) || basicCustomer.getBoxPickMode().equals("0")) {
            if (ToolUtil.isEmpty(storageOutResult.getScattered())) {
                hxStorageOutDetailedService.updaterealNumBySpec(hxStorageOutDetailedParam);//更新实拣数量 = 应拣数量(应急可以取消整箱区扫码拣选)
            }
        }
        //扣减库存
        HxStorageOutDetailedParam hxStorageOutDetailedParamf = new HxStorageOutDetailedParam();
        hxStorageOutDetailedParamf.setStorageNumber(hxStorageOutDetailedParam.getStorageNumber());
        List<HxStorageOutDetailedResult> dlist = hxStorageOutDetailedService.findListBySpec(hxStorageOutDetailedParamf);
        BigDecimal as = new BigDecimal("0");
        BigDecimal shi = new BigDecimal("10");
        List<HxStorageStock> sadd = new ArrayList<HxStorageStock>();
        for (HxStorageOutDetailedResult d : dlist) {
            HxStorageStockParam subHxStorageStockParam = new HxStorageStockParam();
            if (d.getStockId() != null) {
                subHxStorageStockParam.setId(Integer.parseInt(d.getStockId().toString()));
            }
            subHxStorageStockParam.setStockState("正常");
            subHxStorageStockParam.setWarehouseId(storageOutResult.getSetWarehouseId());
            subHxStorageStockParam.setPositionId(d.getPositionId());
            subHxStorageStockParam.setPositionType("拣货位");
            subHxStorageStockParam.setGoodsId(d.getGoodsId());
            List<HxStorageStockResult> subs = hxStorageStockService.findsubListBySpec(subHxStorageStockParam);
            BigDecimal rate = new BigDecimal(d.getRate());//出库换算率
            if (ToolUtil.isEmpty(d.getRealNum())) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); //手动回滚
                return ResponseData.error(d.getGoodsName() + ",未拣货!");
            }
            BigDecimal num = new BigDecimal(d.getNum());//数量
            BigDecimal realNum = new BigDecimal(d.getRealNum());//实拣数量
            if (num.compareTo(realNum) != 0) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); //手动回滚
                return ResponseData.error(d.getGoodsName() + ",应拣与实拣不一致!");
            }
            //实拣基本数量
            BigDecimal realNumJiben = realNum.multiply(new BigDecimal(d.getRate()));
            for (HxStorageStockResult obj : subs) {
                BigDecimal _kcRate = new BigDecimal(obj.getKcRate());
                //修改拣货明细计量
                if (ToolUtil.isEmpty(d.getDetailedDate())) {
                    d.setDetailedDate(obj.getDetailedDate());
                    d.setDaoqiDate(obj.getExpirationDate());
                    HxStorageOutDetailedParam sdp = new HxStorageOutDetailedParam();
                    sdp.setId(d.getId());
                    sdp.setDetailedDate(obj.getDetailedDate());
                    sdp.setDaoqiDate(obj.getExpirationDate());
                    hxStorageOutDetailedService.update(sdp);
                }
                //库存数量大于拣货数量 库存计量需要拆开
                if (obj.getJibenNum().compareTo(realNumJiben) == 1) {
                    //基本单位对应的体积重量
                    BigDecimal goodsVolume = new BigDecimal(obj.getStockVolume()).divide(obj.getJibenNum(), 10, BigDecimal.ROUND_HALF_DOWN);
                    BigDecimal goodsWeight = new BigDecimal(obj.getStockWeight()).divide(obj.getJibenNum(), 10, BigDecimal.ROUND_HALF_DOWN);
                    ;
                    BigDecimal goodsPrice = new BigDecimal(obj.getStockMoney()).divide(obj.getJibenNum(), 10, BigDecimal.ROUND_HALF_DOWN);
                    ;
                    //剩余库存
                    BigDecimal sykc = obj.getJibenNum().subtract(realNumJiben);
                    //修改扣除后的库存计量
                    HxStorageStockParam updateHxStorageStockParam = new HxStorageStockParam();
                    updateHxStorageStockParam.setId(obj.getId());
                    updateHxStorageStockParam.setStockVolume(sykc.multiply(goodsVolume).setScale(4, BigDecimal.ROUND_HALF_DOWN).toString());
                    updateHxStorageStockParam.setStockWeight(sykc.multiply(goodsWeight).setScale(3, BigDecimal.ROUND_HALF_DOWN).toString());
                    updateHxStorageStockParam.setStockMoney(sykc.multiply(goodsPrice).setScale(3, BigDecimal.ROUND_HALF_DOWN).toString());
                    updateHxStorageStockParam.setKcNum(String.valueOf(sykc.divide(_kcRate, 3, BigDecimal.ROUND_HALF_DOWN)));
                    updateHxStorageStockParam.setJibenNum(sykc);
                    hxStorageStockService.update(updateHxStorageStockParam);
                    //添加集货区库存
                    HxStorageStock updateHxStorageStockParamadd = new HxStorageStock();
                    ToolUtil.copyProperties(obj, updateHxStorageStockParamadd);
                    updateHxStorageStockParamadd.setId(null);
                    updateHxStorageStockParamadd.setStorageNumber(storageOutResult.getStorageNumber());
                    updateHxStorageStockParamadd.setStockState("集货");
                    updateHxStorageStockParamadd.setAreaId(null);
                    updateHxStorageStockParamadd.setAreaNumber(null);
                    updateHxStorageStockParamadd.setAreaName("集货区");
//                        updateHxStorageStockParamadd.setPositionId(null);
                    updateHxStorageStockParamadd.setPositionType("集货位");
                    updateHxStorageStockParamadd.setPositionNumber(storageOutResult.getStockPort());
                    updateHxStorageStockParamadd.setTrayNumber(storageOutResult.getTrayNumber());
                    updateHxStorageStockParamadd.setStockVolume(realNumJiben.multiply(goodsVolume).setScale(4, BigDecimal.ROUND_HALF_DOWN).toString());
                    updateHxStorageStockParamadd.setStockWeight(realNumJiben.multiply(goodsWeight).setScale(3, BigDecimal.ROUND_HALF_DOWN).toString());
                    updateHxStorageStockParamadd.setStockMoney(realNumJiben.multiply(goodsPrice).setScale(3, BigDecimal.ROUND_HALF_DOWN).toString());
                    updateHxStorageStockParamadd.setKcNum(String.valueOf(realNumJiben.divide(_kcRate, 3, BigDecimal.ROUND_HALF_DOWN)));
                    updateHxStorageStockParamadd.setJibenNum(realNumJiben);
                    sadd.add(updateHxStorageStockParamadd);
                    realNumJiben = new BigDecimal(0);
                } else {
                    hxStorageStockService.lambdaUpdate()
                            .eq(HxStorageStock::getId, obj.getId())
                            .set(HxStorageStock::getStorageNumber, storageOutResult.getStorageNumber())
                            .set(HxStorageStock::getStockState, "集货")
                            .set(HxStorageStock::getAreaId, null)
                            .set(HxStorageStock::getAreaNumber, null)
                            .set(HxStorageStock::getAreaName, "集货区")
//                                .set(HxStorageStock::getPositionId, null)
                            .set(HxStorageStock::getPositionType, "集货位")
                            .set(HxStorageStock::getPositionNumber, storageOutResult.getStockPort())
                            .set(HxStorageStock::getTrayNumber, storageOutResult.getTrayNumber())
                            .update();
                    realNumJiben = realNumJiben.subtract(obj.getJibenNum());
                }
                //拣货数量为0时，退出循环
                if (realNumJiben.compareTo(as) == 0) {
                    break;
                }
            }
            //库存循环完，还有未扣库存，说明货物不足
            if (realNumJiben.compareTo(as) == 1) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); //手动回滚
                return ResponseData.error(d.getGoodsName() + ",拣货位货物不足!");
            }
        }
        //批量添加新库存
        if (sadd.size() > 0) {
            hxStorageStockService.saveBatch(sadd);
        }
        if (ToolUtil.isEmpty(basicCustomer.getNeedCheck()) || basicCustomer.getNeedCheck().equals("2")) {//如果不质检
            //新增货运订单
            if (ToolUtil.isNotEmpty(basicCustomer.getGenerateTms())) {
                if (basicCustomer.getGenerateTms().equals("1")) {
                    List<OrderTransportDetailedParam> transportdList = new ArrayList<OrderTransportDetailedParam>();//批量保存的 货运订单list
                    BasicOperate basicOperate = basicOperateService.getById(basicCustomer.getCustomerOperateId());
                    String trayCode = getOperateIdOrderPrefix(user);
                    String name = "零脉";

                    OrderTransportParam addp = new OrderTransportParam();
                    addp.setOperateId(Long.parseLong(basicCustomer.getCustomerOperateId().toString()));//分公司id
                    addp.setOperateName(basicOperate.getOperateName());//公司名称
                    addp.setCustomerOrder(storageOutResult.getTrayNumber() + "_" + storageOutResult.getStorageNumber());
                    addp.setTransportNumber(trayCode + "HY" + cn.stylefeng.guns.core.util.DateUtil.getDatesBch() + DateUtil.getRandomNumber());
                    addp.setOrderNumber(storageOutResult.getStorageNumber());
                    addp.setDemolition(storageOutResult.getScattered());
                    addp.setLmOrderType(storageOutResult.getOrderType());
                    addp.setLmAssociationOrder(storageOutResult.getAssociationOrder());
                    if (ToolUtil.isNotEmpty(storageOutResult.getPieceNumber())) {
                        addp.setPieceNumber(storageOutResult.getPieceNumber());
                    } else {
                        if (ToolUtil.isNotEmpty(storageOutResult.getScattered())) {
                            BigDecimal realNum = new BigDecimal(storageOutResult.getRealNum());
                            if (realNum.compareTo(as) == 1) {
                                BigDecimal pieceNumberbig = realNum.divide(shi, 3, BigDecimal.ROUND_HALF_DOWN);
                                addp.setPieceNumber(pieceNumberbig + "");
                            } else {
                                addp.setPieceNumber("0");
                            }
                        } else {
                            addp.setPieceNumber("0");
                        }
                    }
                    addp.setOrderSource("零脉");
                    addp.setCustomerId(Long.parseLong(basicCustomer.getId().toString()));//客户id
                    addp.setCustomerName(basicCustomer.getCustomerName());//客户名称
                    addp.setUndertime(DateUtil2.getDateS());//下单时间
                    addp.setSetMentiontime(storageOutResult.getPeisongTime());//发货日期

                    addp.setXlbSetUnitId(storageOutResult.getXlbSetUnitId());
                    addp.setSetUnit(storageOutResult.getSetUnit());//装货单位
                    addp.setSetUnitId(storageOutResult.getSetUnitId());//装货单位id
                    addp.setXlbSetWarehouse(storageOutResult.getSetWarehouse());
                    addp.setXlbSetWarehouseId(storageOutResult.getXlbSetWarehouseId());
                    addp.setXlbClientId(storageOutResult.getXlbClientId());
                    addp.setGetUnit(storageOutResult.getGetUnit());
                    addp.setGetUnitId(storageOutResult.getGetUnitId());
                    addp.setStockPort(storageOutResult.getStockPort());//备货口

                    toDealWith4(addp);//处理单位和地址

                    addp.setDeptId(user.getDeptId());
                    addp.setDeliverId(user.getDeliverId());
                    addp.setCreateName(name);
                    addp.setCreateTime(new Date());
                    addp.setGoodsNum(storageOutResult.getGoodsNum());

                    addp.setTooNum("0");
                    addp.setTooVolume("0");
                    addp.setTstate("待调");
                    BigDecimal TotalNum = new BigDecimal("0");//货物单总数
                    BigDecimal TotalVolume = new BigDecimal("0");//货物单总体积
                    //货品信息
//                        HxBasicGoodsParam q = new HxBasicGoodsParam();
//                        q.setDeptId(storageOutResult.getDeptId());
//                        List<HxBasicGoodsResult> hxBasicGoodsResults = goodsService.findlistAllBySpec(q, null, Long.valueOf(basicCustomer.getCustomerOperateId()));
                    hxStorageOutDetailedParamf = new HxStorageOutDetailedParam();
                    hxStorageOutDetailedParamf.setStorageNumber(hxStorageOutDetailedParam.getStorageNumber());
                    List<HxStorageOutDetailedResult> hxStorageOutDetaileds = hxStorageOutDetailedService.findListBySpec(hxStorageOutDetailedParamf);
                    Map<String, HxStorageOutDetailedResult> hxBasicGoodsMap = new HashedMap();
                    for (HxStorageOutDetailedResult obj : hxStorageOutDetaileds) {
                        hxBasicGoodsMap.put(obj.getGoodsId().toString(), obj);
                    }
                    //根据拣货单号获取库存列表
                    HxStorageStockParam hxStorageStockParam = new HxStorageStockParam();
                    hxStorageStockParam.setStorageNumber(storageOutResult.getStorageNumber());
                    hxStorageStockParam.setWarehouseId(storageOutResult.getSetWarehouseId());
                    List<HxStorageStockResult> hxStorageStockStorageNumbers = hxStorageStockService.findListByStorageNumber1(hxStorageStockParam);
                    //库位信息
                    List<BasicPosition> basicPositions = basicPositionService.lambdaQuery()
                            .eq(BasicPosition::getWarehouseId, storageOutResult.getSetWarehouseId())
                            .eq(BasicPosition::getPositionType, "拣货位")
                            .list();
                    Map<String, BasicPosition> basicPositionMap = new HashedMap();
                    for (BasicPosition obj : basicPositions) {
                        basicPositionMap.put(obj.getId().toString(), obj);
                    }

                    for (HxStorageStockResult obj : hxStorageStockStorageNumbers) {
                        //新增货运明细
                        OrderTransportDetailedParam outTranDetailed = new OrderTransportDetailedParam();
                        outTranDetailed.setTransportNumber(addp.getTransportNumber());
                        if (ToolUtil.isNotEmpty(obj.getPositionId()) && basicPositionMap.get(obj.getPositionId().toString()) != null) {
                            outTranDetailed.setXlbPositionId(basicPositionMap.get(obj.getPositionId().toString()).getPositionXlbId());
                            outTranDetailed.setPositionNumber(basicPositionMap.get(obj.getPositionId().toString()).getPositionNumber());
                        }
                        outTranDetailed.setPositionId(obj.getPositionId());

                        outTranDetailed.setGoodsVolume(obj.getGoodsVolume());
                        outTranDetailed.setTransportPutvolume(obj.getStockVolume());
                        outTranDetailed.setGoodsWeight(obj.getGoodsWeight());
                        outTranDetailed.setTransportWeight(obj.getStockWeight());
                        outTranDetailed.setUnitprice(hxBasicGoodsMap.get(obj.getGoodsId().toString()).getGoodsPrice());
                        //金额=单价/rate*基本数量
                        if (ToolUtil.isNotEmpty(hxBasicGoodsMap.get(obj.getGoodsId().toString()).getGoodsPrice()) && ToolUtil.isNotEmpty(hxBasicGoodsMap.get(obj.getGoodsId().toString()).getRate())) {
                            BigDecimal transportMoney = obj.getJibenNum().multiply(new BigDecimal(hxBasicGoodsMap.get(obj.getGoodsId().toString()).getGoodsPrice())).divide(new BigDecimal(hxBasicGoodsMap.get(obj.getGoodsId().toString()).getRate()), 3, BigDecimal.ROUND_HALF_DOWN).setScale(3, BigDecimal.ROUND_HALF_DOWN);
                            outTranDetailed.setTransportMoney(transportMoney.toString());
                        }


                        outTranDetailed.setXlbGoodsId(hxBasicGoodsMap.get(obj.getGoodsId().toString()).getXlbGoodsId());
                        outTranDetailed.setGoodId(obj.getGoodsId());
                        outTranDetailed.setGoodsName(obj.getGoodsName());
                        outTranDetailed.setGoodsNumber(obj.getGoodsNumber());
                        outTranDetailed.setGoodsPcode69(obj.getGoodsPcode69());
                        outTranDetailed.setGoodsUnit(obj.getKcUnit());
                        outTranDetailed.setGoodsSpecs(obj.getGoodsSpecs());

                        outTranDetailed.setJibenUnit(obj.getJibenUnit());
                        outTranDetailed.setJibenNum(String.valueOf(obj.getJibenNum()));
                        outTranDetailed.setBalenum(obj.getKcNum());
                        outTranDetailed.setNum(obj.getKcNum());
                        outTranDetailed.setRate(obj.getKcRate());

                        outTranDetailed.setDetailedDate(obj.getDetailedDate());
                        outTranDetailed.setDaoqiDate(obj.getExpirationDate());

                        outTranDetailed.setNotnum(outTranDetailed.getNum());
                        outTranDetailed.setNotvolume(outTranDetailed.getTransportPutvolume());
                        BigDecimal num = new BigDecimal(outTranDetailed.getNum());
                        if (num.compareTo(as) == 1) {
                            transportdList.add(outTranDetailed);
                        } else {
                            continue;
                        }

                        BigDecimal transportPutvolume = new BigDecimal(outTranDetailed.getTransportPutvolume());
                        BigDecimal nTotalNum = TotalNum.add(num);
                        TotalNum = nTotalNum;
                        BigDecimal nTotalVolume = TotalVolume.add(transportPutvolume);
                        TotalVolume = nTotalVolume;
                    }
                    addp.setTotalNum(TotalNum.setScale(3, BigDecimal.ROUND_HALF_DOWN).toString());
                    addp.setTotalVolume(TotalVolume.setScale(4, BigDecimal.ROUND_HALF_DOWN).toString());
                    if (TotalNum.compareTo(as) == 1) {
                        orderTransportService.add(addp);
                        if (transportdList.size() > 0) {
                            this.orderTransportDetailedService.saveBatchList(transportdList);
                        }
                    }
                }
            }
        }
        if (storageOutResult.getAgvRobot().equals("2") && !"人工处理".equals(hxStorageOutDetailedParam.getStockPort())) {
            TuskAgvTaskParam tuskAgvTaskParam = new TuskAgvTaskParam();
            tuskAgvTaskParam.setSrcPositionCode(pickupPoint);
            tuskAgvTaskParam.setPriority(priority);
            String stockPort = storageOutResult.getStockPort();
            if (stockPort.length() == 1) {
                stockPort = "00" + stockPort;
            }
            if (stockPort.length() == 2) {
                stockPort = "0" + stockPort;
            }
            tuskAgvTaskParam.setTarPositionCode("H" + stockPort);
            //如果传入目标点，则根据目标点送达
            if (ToolUtil.isNotEmpty(hxStorageOutDetailedParam.getStockPort())) {
                tuskAgvTaskParam.setTarPositionCode(hxStorageOutDetailedParam.getStockPort());
            }
            if (user != null && user.getUserId() != null) {
                //创建人
                tuskAgvTaskParam.setCreateUser(user.getUserId());
                //修改人
                tuskAgvTaskParam.setUpdateUser(user.getUserId());
            }
            // 创建时间
            tuskAgvTaskParam.setCreateTime(new Date());
            resdata = tuskAgvTaskService.addTask(tuskAgvTaskParam);
            if (!resdata.getSuccess()) {
                resdata.setCode(777);
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); //手动回滚
                return resdata;
            }
        }
        if (storageOutResult.getAgvRobot().equals("1") && !"人工处理".equals(hxStorageOutDetailedParam.getStockPort())) {
            HikAgvTaskJLParam hikAgvTaskJLParam = new HikAgvTaskJLParam();
            hikAgvTaskJLParam.setDeptId(user.getDeptId() + "");
            hikAgvTaskJLParam.setSrcPositionCode(pickupPoint);
            hikAgvTaskJLParam.setPriority(priority);
            if (user != null && user.getUserId() != null) {
                //创建人
                hikAgvTaskJLParam.setCreateUser(user.getUserId());
            }
            //创建时间
            hikAgvTaskJLParam.setCreateTime(new Date());
            hikAgvTaskJLParam.setUpdateTime(new Date());

            if (hikAgvTaskJLParam.getTaskTyp() == null || "".equals(hikAgvTaskJLParam.getTaskTyp())) {
                hikAgvTaskJLParam.setTaskTyp("F14");
            }

            if (hikAgvTaskJLParam.getCtnrTyp() == null || "".equals(hikAgvTaskJLParam.getCtnrTyp())) {
                hikAgvTaskJLParam.setCtnrTyp("1");
            }
            hikAgvTaskJLParam.setStat("01");
            hikAgvTaskJLParam.setSrcPositionType("00");
            hikAgvTaskJLParam.setTarPositionType("06");
            String stockPort = storageOutResult.getStockPort();
//            if(stockPort.length() == 1) {
//                stockPort = "00"+stockPort;
//            }
//            if(stockPort.length() == 2) {
//                stockPort = "0"+stockPort;
//            }
            hikAgvTaskJLParam.setTarPositionCode(stockPort);
            //如果传入目标点，则根据目标点送达
            if (ToolUtil.isNotEmpty(hxStorageOutDetailedParam.getStockPort())) {
                hikAgvTaskJLParam.setTarPositionCode(hxStorageOutDetailedParam.getStockPort());
            }

            hikAgvTaskJlService.addTaskcc(hikAgvTaskJLParam);

        }
        return ResponseData.success(hxStorageOutDetailedParam.getStorageNumber());
    }

    @Autowired
    private TuskAgvTaskService tuskAgvTaskService;
    @Autowired
    private HikAgvTaskJLService hikAgvTaskJlService;

    @Override
    @Transactional(rollbackFor = Exception.class, timeout = 60)
    public ResponseData reviewCompleted(HxStorageOutParam hxStorageOutParam, User user) {
        HxStorageOutResult res = this.findCountGoodsBySpec(hxStorageOutParam);
        if (res == null || !res.getStorageState().equals("复核中")) {
            return ResponseData.error("拣货任务不存在或已复核");
        }
        hxStorageOutParam.setId(res.getId());
        hxStorageOutParam.setStorageState("已完成");
        hxStorageOutParam.setQualityCompleteTime(new Date());
        this.update(hxStorageOutParam);

        HxStorageOutDetailedParam detailedParam = new HxStorageOutDetailedParam();
        detailedParam.setStorageNumber(hxStorageOutParam.getStorageNumber());
        List<HxStorageOutDetailedResult> dlist = hxStorageOutDetailedService.findNumNotRealNumListBySpec(detailedParam);
        BigDecimal as = new BigDecimal("0");
        for (HxStorageOutDetailedResult dres : dlist) {
            BigDecimal realNumb = new BigDecimal(dres.getRealNum());
            if (ToolUtil.isEmpty(dres.getQualityNum())) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); //手动回滚
                return ResponseData.error(dres.getGoodsName() + ",质检数量不得为空!");
            }
            BigDecimal qualityNumb = new BigDecimal(dres.getQualityNum());

            if (qualityNumb.compareTo(realNumb) != 0) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); //手动回滚
                return ResponseData.error(dres.getGoodsName() + ",质检数量与拣货数量不相等!");
            }
        }

        BasicCustomer basicCustomer = basicCustomerService.getById(res.getCustomerId());
        if (ToolUtil.isNotEmpty(basicCustomer.getNeedCheck()) && basicCustomer.getNeedCheck().equals("1")) {//如果质检
            //新增货运订单
            if (ToolUtil.isNotEmpty(basicCustomer.getGenerateTms())) {
                if (basicCustomer.getGenerateTms().equals("1")) {
                    HxStorageOutDetailedParam hxStorageOutDetailedParamf = new HxStorageOutDetailedParam();
                    hxStorageOutDetailedParamf.setStorageNumber(res.getStorageNumber());
//	    	            List<HxStorageOutDetailedResult> dlist2 = hxStorageOutDetailedService.findListBySpec(hxStorageOutDetailedParamf);

                    List<OrderTransportDetailedParam> transportdList = new ArrayList<OrderTransportDetailedParam>();//批量保存的 货运订单list
                    BasicOperate basicOperate = basicOperateService.getById(basicCustomer.getCustomerOperateId());
                    String trayCode = getOperateIdOrderPrefix(user);
                    String name = "零脉";

                    OrderTransportParam addp = new OrderTransportParam();
                    addp.setOperateId(Long.parseLong(basicCustomer.getCustomerOperateId().toString()));//分公司id
                    addp.setOperateName(basicOperate.getOperateName());//公司名称
                    addp.setCustomerOrder(res.getTrayNumber() + "_" + res.getStorageNumber());
                    addp.setTransportNumber(trayCode + "HY" + cn.stylefeng.guns.core.util.DateUtil.getDatesBch() + DateUtil.getRandomNumber());
                    addp.setOrderNumber(res.getStorageNumber());
                    addp.setDemolition(res.getScattered());
                    addp.setLmOrderType(res.getOrderType());
                    addp.setLmAssociationOrder(res.getAssociationOrder());
                    addp.setOrderSource("零脉");
                    addp.setCustomerId(Long.parseLong(basicCustomer.getId().toString()));//客户id
                    addp.setCustomerName(basicCustomer.getCustomerName());//客户名称
                    addp.setUndertime(DateUtil2.getDateS());//下单时间
                    addp.setSetMentiontime(res.getPeisongTime());//发货日期

                    addp.setXlbSetUnitId(res.getXlbSetUnitId());
                    addp.setSetUnit(res.getSetUnit());//装货单位
                    addp.setSetUnitId(res.getSetUnitId());//装货单位id
                    addp.setXlbSetWarehouse(res.getSetWarehouse());
                    addp.setXlbSetWarehouseId(res.getXlbSetWarehouseId());
                    addp.setXlbClientId(res.getXlbClientId());
                    addp.setGetUnit(res.getGetUnit());
                    addp.setGetUnitId(res.getGetUnitId());
                    addp.setStockPort(res.getStockPort());//备货口

                    toDealWith4(addp);//处理单位和地址

                    addp.setDeptId(user.getDeptId());
                    addp.setDeliverId(user.getDeliverId());
                    addp.setCreateName(name);
                    addp.setGoodsNum(res.getGoodsNum());
                    addp.setCreateTime(new Date());

                    addp.setTooNum("0");
                    addp.setTooVolume("0");
                    addp.setTstate("待调");
                    BigDecimal TotalNum = new BigDecimal("0");//货物单总数
                    BigDecimal TotalVolume = new BigDecimal("0");//货物单总体积
                    //货品信息
//                        HxBasicGoodsParam q = new HxBasicGoodsParam();
//                        q.setDeptId(res.getDeptId());
//                        List<HxBasicGoodsResult> hxBasicGoodsResults = goodsService.findlistAllBySpec(q, null, Long.valueOf(basicCustomer.getCustomerOperateId()));
//                        Map<String,HxBasicGoodsResult> hxBasicGoodsMap = new HashedMap();
//                        for(HxBasicGoodsResult obj : hxBasicGoodsResults){
//                            hxBasicGoodsMap.put(obj.getId().toString(),obj);
//                        }
                    hxStorageOutDetailedParamf = new HxStorageOutDetailedParam();
                    hxStorageOutDetailedParamf.setStorageNumber(res.getStorageNumber());
                    List<HxStorageOutDetailedResult> hxStorageOutDetaileds = hxStorageOutDetailedService.findListBySpec(hxStorageOutDetailedParamf);
                    Map<String, HxStorageOutDetailedResult> hxBasicGoodsMap = new HashedMap();
                    for (HxStorageOutDetailedResult obj : hxStorageOutDetaileds) {
                        hxBasicGoodsMap.put(obj.getGoodsId().toString(), obj);
                    }
                    //根据拣货单号获取库存列表
                    HxStorageStockParam hxStorageStockParam = new HxStorageStockParam();
                    hxStorageStockParam.setStorageNumber(res.getStorageNumber());
                    hxStorageStockParam.setWarehouseId(res.getSetWarehouseId());
                    List<HxStorageStockResult> hxStorageStockStorageNumbers = hxStorageStockService.findListByStorageNumber1(hxStorageStockParam);
                    //库位信息
                    List<BasicPosition> basicPositions = basicPositionService.lambdaQuery()
                            .eq(BasicPosition::getWarehouseId, res.getSetWarehouseId())
                            .eq(BasicPosition::getPositionType, "拣货位")
                            .list();
                    Map<String, BasicPosition> basicPositionMap = new HashedMap();
                    for (BasicPosition obj : basicPositions) {
                        basicPositionMap.put(obj.getId().toString(), obj);
                    }

                    for (HxStorageStockResult obj : hxStorageStockStorageNumbers) {
                        //新增货运明细
                        OrderTransportDetailedParam outTranDetailed = new OrderTransportDetailedParam();
                        outTranDetailed.setTransportNumber(addp.getTransportNumber());

                        if (ToolUtil.isNotEmpty(obj.getPositionId()) && basicPositionMap.get(obj.getPositionId().toString()) != null) {
                            outTranDetailed.setXlbPositionId(basicPositionMap.get(obj.getPositionId().toString()).getPositionXlbId());
                            outTranDetailed.setPositionNumber(basicPositionMap.get(obj.getPositionId().toString()).getPositionNumber());
                        }
                        outTranDetailed.setPositionId(obj.getPositionId());

                        outTranDetailed.setGoodsVolume(obj.getGoodsVolume());
                        outTranDetailed.setTransportPutvolume(obj.getStockVolume());
                        outTranDetailed.setGoodsWeight(obj.getGoodsWeight());
                        outTranDetailed.setTransportWeight(obj.getStockWeight());
                        outTranDetailed.setUnitprice(hxBasicGoodsMap.get(obj.getGoodsId().toString()).getGoodsPrice());
                        //金额=单价/rate*基本数量
                        if (ToolUtil.isNotEmpty(hxBasicGoodsMap.get(obj.getGoodsId().toString()).getGoodsPrice()) && ToolUtil.isNotEmpty(hxBasicGoodsMap.get(obj.getGoodsId().toString()).getRate())) {
                            BigDecimal transportMoney = obj.getJibenNum().multiply(new BigDecimal(hxBasicGoodsMap.get(obj.getGoodsId().toString()).getGoodsPrice())).divide(new BigDecimal(hxBasicGoodsMap.get(obj.getGoodsId().toString()).getRate()), 3, BigDecimal.ROUND_HALF_DOWN).setScale(3, BigDecimal.ROUND_HALF_DOWN);
                            outTranDetailed.setTransportMoney(transportMoney.toString());
                        }
//                            outTranDetailed.setTransportMoney(obj.getStockMoney());

                        outTranDetailed.setXlbGoodsId(hxBasicGoodsMap.get(obj.getGoodsId().toString()).getXlbGoodsId());
                        outTranDetailed.setGoodId(obj.getGoodsId());
                        outTranDetailed.setGoodsName(obj.getGoodsName());
                        outTranDetailed.setGoodsNumber(obj.getGoodsNumber());
                        outTranDetailed.setGoodsPcode69(obj.getGoodsPcode69());
                        outTranDetailed.setGoodsUnit(obj.getKcUnit());
                        outTranDetailed.setGoodsSpecs(obj.getGoodsSpecs());

                        outTranDetailed.setJibenUnit(obj.getJibenUnit());
                        outTranDetailed.setJibenNum(String.valueOf(obj.getJibenNum()));
                        outTranDetailed.setBalenum(obj.getKcNum());
                        outTranDetailed.setNum(obj.getKcNum());
                        outTranDetailed.setRate(obj.getKcRate());

                        outTranDetailed.setDetailedDate(obj.getDetailedDate());
                        outTranDetailed.setDaoqiDate(obj.getExpirationDate());

                        outTranDetailed.setNotnum(outTranDetailed.getNum());
                        outTranDetailed.setNotvolume(outTranDetailed.getTransportPutvolume());
                        BigDecimal num = new BigDecimal(outTranDetailed.getNum());
                        if (num.compareTo(as) == 1) {
                            transportdList.add(outTranDetailed);
                        } else {
                            continue;
                        }

                        BigDecimal transportPutvolume = new BigDecimal(outTranDetailed.getTransportPutvolume());
                        BigDecimal nTotalNum = TotalNum.add(num);
                        TotalNum = nTotalNum;
                        BigDecimal nTotalVolume = TotalVolume.add(transportPutvolume);
                        TotalVolume = nTotalVolume;
                    }
                    addp.setTotalNum(TotalNum.setScale(3, BigDecimal.ROUND_HALF_DOWN).toString());
                    addp.setTotalVolume(TotalVolume.setScale(4, BigDecimal.ROUND_HALF_DOWN).toString());
                    if (TotalNum.compareTo(as) == 1) {
                        orderTransportService.add(addp);
                        if (transportdList.size() > 0) {
                            this.orderTransportDetailedService.saveBatchList(transportdList);
                        }
                    }
                }
            }
        }
        return ResponseData.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class, timeout = 60)
    public ResponseData btnCompleted(HxStorageOutParam hxStorageOutParam) {
        HxStorageOutResult res = this.findBySpec(hxStorageOutParam);
        if (res == null || !res.getStorageState().equals("复核中")) {
            return ResponseData.error("拣货任务不存在或已复核");
        }
        hxStorageOutParam.setId(res.getId());
        hxStorageOutParam.setStorageState("已完成");
        hxStorageOutParam.setQualityCompleteTime(new Date());
        this.update(hxStorageOutParam);

        HxStorageOutDetailedParam hxStorageOutDetailedParam = new HxStorageOutDetailedParam();
        hxStorageOutDetailedParam.setStorageNumber(hxStorageOutParam.getStorageNumber());
        hxStorageOutDetailedService.updatequalityNumBySpec(hxStorageOutDetailedParam);
        return ResponseData.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class, timeout = 180)
    public ResponseData btnAgvStorage(Integer[] ids, User user) {
        if (ToolUtil.isEmpty(ids)) {
            return ResponseData.error("请先选择要操作的记录！");
        }
        try {
            List<HxStorageOut> hxStorageOuts = this.lambdaQuery()
                    .in(HxStorageOut::getId, ids).list();
            BasicCustomer basicCustomer = null;
            List<String> storageNumberList = new ArrayList<>();
            for (HxStorageOut obj : hxStorageOuts) {
                storageNumberList.add(obj.getStorageNumber());
                if (basicCustomer == null) {
                    basicCustomer = basicCustomerService.getById(obj.getCustomerId());
                }
//                if ("1".equals(basicCustomer.getBoxPickMode()) && (ToolUtil.isEmpty(obj.getPrintNumb()) || "0".equals(obj.getPrintNumb()))) {
//                    return ResponseData.error("请先打印任务[" + obj.getStorageNumber() + "]的标签");
//                } else
                if(!"拆零".equals(obj.getScattered()) && !"1".equals(basicCustomer.getBoxPickMode()) && (ToolUtil.isEmpty(obj.getPrintNumb()) || "0".equals(obj.getPrintNumb()))){
                    return ResponseData.error("请先打印任务[" + obj.getStorageNumber() + "]的标签");
                }
                if ("是".equals(obj.getAgvStorageTask())) {
                    return ResponseData.error("任务[" + obj.getStorageNumber() + "]已下发，无法多次操作");
                }
                if (!"待拣货".equals(obj.getStorageState())) {
                    return ResponseData.error("任务[" + obj.getStorageNumber() + "]状态不是[待拣货]，无法操作");
                }
                if (ToolUtil.isEmpty(obj.getStockPort())) {
                    return ResponseData.error("任务[" + obj.getStorageNumber() + "]请先分配集货位！");
                }

            }
            //查找拣货明细
            Map<String, List<HxStorageOutDetailed>> hxStorageOutDetailedMap = new HashMap<>();
            List<HxStorageOutDetailed> hxStorageOutDetaileds = hxStorageOutDetailedService.lambdaQuery()
                    .in(HxStorageOutDetailed::getStorageNumber, storageNumberList)
                    .list();
            List<HxStorageOutDetailed> _hxStorageOutDetailedList = null;
            for (HxStorageOutDetailed obj : hxStorageOutDetaileds) {
                if (hxStorageOutDetailedMap.get(obj.getStorageNumber()) == null) {
                    _hxStorageOutDetailedList = new ArrayList<>();
                    _hxStorageOutDetailedList.add(obj);
                    hxStorageOutDetailedMap.put(obj.getStorageNumber(), _hxStorageOutDetailedList);
                } else {
                    hxStorageOutDetailedMap.get(obj.getStorageNumber()).add(obj);
                }
            }
            //开始下发拣货任务
            List<AgvStorageTask> agvStorageTasks = new ArrayList<>();
            for (HxStorageOut obj : hxStorageOuts) {
                //创建AGV任务主表
                AgvStorageTask agvStorageTask = new AgvStorageTask();
                //主键
                agvStorageTask.setId(IdUtil.simpleUUID());
                //订单号
                agvStorageTask.setStorageNumber(obj.getStorageNumber());
                //任务编号
                agvStorageTask.setTaskNo(CodeGenerateUtil.generate());
                //AGV机器人类型
                if ("1".equals(obj.getAgvRobot())) { //海康
                    agvStorageTask.setAgvTyp("HIK");
                    //暂时写死 目标点
                    agvStorageTask.setWebCode(obj.getStockPort());
                } else if ("2".equals(obj.getAgvRobot())) { //TUSK
                    agvStorageTask.setAgvTyp("TUSK");
                    //暂时写死 目标点
                    agvStorageTask.setWebCode("H" + StringUtils.leftPad(obj.getStockPort(), 3, "0"));
                }
                //创建人
                if (user != null) {
                    agvStorageTask.setCreateUser(user.getAccount());
                }
                //基础URL
                if (basicCustomer != null && ToolUtil.isNotEmpty(basicCustomer.getAgvBaseUrl())) {
                    agvStorageTask.setAgvApiBaseUrl(basicCustomer.getAgvBaseUrl());
                }
                //创建时间
                agvStorageTask.setCreateTime(new Date());
                //交付客户id
                agvStorageTask.setDeliverId(obj.getDeliverId());
                //部门id
                agvStorageTask.setDeptId(obj.getDeptId());
                //发货仓库id
                agvStorageTask.setSetWarehouseId(obj.getSetWarehouseId());
                //是否拆托 默认否
                agvStorageTask.setDisPallet("否");
                //新增
                this.agvStorageTaskMapper.insert(agvStorageTask);
                agvStorageTasks.add(agvStorageTask);
                //明细
                List<AgvStorageTaskDetail> saveList = new ArrayList<>();
                AgvStorageTaskDetail agvStorageTaskDetail = null;
                for (HxStorageOutDetailed _obj : hxStorageOutDetailedMap.get(obj.getStorageNumber())) {
                    agvStorageTaskDetail = new AgvStorageTaskDetail();
                    agvStorageTaskDetail.setId(IdUtil.simpleUUID()); //主键
                    agvStorageTaskDetail.setStorageTaskId(agvStorageTask.getId()); //agv拣货任务ID
                    agvStorageTaskDetail.setStorageOutDetailId(_obj.getId().longValue()); //拣货明细ID
                    agvStorageTaskDetail.setPositionId(_obj.getPositionId()); //库位id
                    agvStorageTaskDetail.setPositionNumber(_obj.getPositionNumber());
                    agvStorageTaskDetail.setPositionPickingorder(Integer.valueOf(_obj.getPositionPickingorder()));
                    agvStorageTaskDetail.setGoodsId(_obj.getGoodsId());
                    agvStorageTaskDetail.setGoodsNumber(_obj.getGoodsNumber());
                    agvStorageTaskDetail.setGoodsName(_obj.getGoodsName());
                    agvStorageTaskDetail.setUnit(_obj.getUnit());
                    agvStorageTaskDetail.setRate(new BigDecimal(_obj.getRate()));
                    agvStorageTaskDetail.setNum(new BigDecimal(_obj.getNum()).setScale(3, BigDecimal.ROUND_HALF_UP));
                    saveList.add(agvStorageTaskDetail);
                }
                //批量保存
                if (saveList != null && saveList.size() > 0) {
                    this.agvStorageTaskDetailService.saveBatch(saveList);
                }

                HxStorageOutParam update = new HxStorageOutParam();
                update.setId(obj.getId());
                update.setStorageState("拣货中");
                update.setStorageUser("待绑定");
                update.setStorageUserName("待绑定");
                update.setAgvStorageTask("是");
                update.setStorageTime(new Date());
                this.update(update);
            }
            //批量呼叫小车
            for (AgvStorageTask agvStorageTask : agvStorageTasks) {
                //根据拣货单获取拣货单中未拣商品和对应库位
                List<AgvStorageTaskDetailResult> agvStorageTaskDetailList = this.agvStorageTaskDetailMapper.getNextTaskGoodList(AgvStorageTaskDetailParam.builder()
                        .storageTaskId(agvStorageTask.getId())
                        .picked("否")
                        .limit(" 1 ")
                        .build());
                AgvStorageTaskDetailResult agvStorageTaskDetail = agvStorageTaskDetailList.get(0);
                /**
                 * 根据库位编号，获取APR编号
                 */
                AgvStoragePosition agvStoragePosition = agvStoragePositionService.lambdaQuery()
                        .eq(AgvStoragePosition::getSetWarehouseId, agvStorageTask.getSetWarehouseId())
                        .eq(AgvStoragePosition::getPositionNumber, agvStorageTaskDetail.getPositionNumber())
                        .one();
                if (agvStoragePosition == null) {
                    throw new Exception("AGV拣货位[" + agvStorageTaskDetail.getPositionNumber() + "]不存在！");
                }
                //如果是海康机器人
                if ("HIK".equals(agvStorageTask.getAgvTyp())) {
                    //封装接口信息
                    HikAgvTaskParam param = new HikAgvTaskParam();
                    param.setTaskNo(agvStorageTask.getTaskNo());
                    param.setPositionType("1");
                    param.setStartArea(agvStoragePosition.getAgvPick());
                    param.setEndcargoInfo(agvStorageTaskDetail.getPositionNumber());
                    HikRsVo hikRsVo = HikApiUtils.genctnrBinTask(agvStorageTask.getAgvApiBaseUrl(), param);
                    if (hikRsVo == null) {
                        throw new Exception("接口调用错误");
                    } else if (!"0".equals(hikRsVo.getCode())) {
                        throw new Exception(hikRsVo.getMessage());
                    }
                } else if ("TUSK".equals(agvStorageTask.getAgvTyp())) {
                    CreateSortParam param = new CreateSortParam();
                    param.setTaskId(agvStorageTask.getTaskNo());
                    //取托盘
                    param.getTargetActions().add(TargetActionsVo.builder()
                            .target(agvStoragePosition.getAgvPick())
                            .action("GET")
                            .build());

                    String positionNumber = null;
                    if (agvStoragePosition != null) {
                        positionNumber = agvStoragePosition.getAprCode();
                    } else {
                        positionNumber = agvStorageTaskDetail.getPositionNumber();
                    }
                    //取货点
                    param.getTargetActions().add(TargetActionsVo.builder()
                            .target(positionNumber)
                            .action("MOVE")
                            .build());
                    TuskRsVo tuskRs = TustApiUtils.createSortTask(agvStorageTask.getAgvApiBaseUrl(), param);
                    if (tuskRs == null) {
                        throw new Exception("接口调用错误");
                    } else if (tuskRs.getCode() != 200) {
                        throw new Exception(tuskRs.getMsg());
                    }
                }
                //修改拣货状态
                AgvStorageTaskParam update = new AgvStorageTaskParam();
                update.setId(agvStorageTask.getId());
                update.setStat("10");
                update.setCurrTask(agvStorageTaskDetail.getId());
                agvStorageTaskService.update(update);
            }
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); //手动回滚
            return ResponseData.error(e.getMessage());
        }

        return ResponseData.success();
    }

    @Override
    @Transactional
    public ResponseData btnDpsStorage(List<DpsMidOrdersCVo> dpsMidOrdersCAddPList, DpsZcServer dpsZcServer, Set<Integer> ids, User user) throws Exception {
        Connection conn = null;
        PreparedStatement ps = null;
        try {
            conn = MssqlUtils.getConnection(dpsZcServer.getIp(), dpsZcServer.getPort(), dpsZcServer.getDbName(), dpsZcServer.getDbUser(), dpsZcServer.getDbPwd());
            conn.setAutoCommit(false);
            ps = conn.prepareStatement(this.getInsertMidOrdersCSql(dpsZcServer.getDbTable()));

            int cnt = 0;
            for (DpsMidOrdersCVo obj : dpsMidOrdersCAddPList) {
                cnt++;
                ps.setString(1, obj.getOrderid());
                ps.setString(2, obj.getSku());
                ps.setString(3, obj.getMatchid());
                ps.setInt(4, obj.getQuantity());
                ps.setString(5, obj.getTolocation());
                ps.setString(6, obj.getArea());
                ps.setString(7, obj.getState());
                ps.setString(8, obj.getState());
                ps.setString(9, obj.getDowndate());
                ps.setString(10, obj.getShopid());
                ps.setString(11, obj.getDiscount());
                ps.setString(12, obj.getBarcode());
                ps.setString(13, obj.getGoodsname());
                ps.setString(14, obj.getWmsboxcode());
                ps.setString(15, obj.getShopname());
                ps.setString(16, obj.getWmsorderid());
                ps.addBatch();
            }
            if (cnt > 0) {
                ps.executeBatch();
            }
            this.lambdaUpdate()
                    .set(HxStorageOut::getStorageState, "拣货中")
                    .set(HxStorageOut::getStorageUser, "DPS")
                    .set(HxStorageOut::getStorageUserName, "DPS")
                    .set(HxStorageOut::getStorageTime, new Date())
                    .in(HxStorageOut::getId, ids)
                    .update();
            conn.commit();
        } catch (SQLException e) {
            e.printStackTrace();
            JdbcUtls.rollback(conn);
            throw new Exception(e.getMessage());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            throw new Exception(e.getMessage());
        } finally {
            JdbcUtls.closeAll(null, ps, conn);
        }

        return ResponseData.success();
    }

    private String getInsertMidOrdersCSql(String tableName) {
        StringBuffer sql = new StringBuffer();
        sql.append("insert into ").append(tableName).append(" (");
        sql.append("orderid");
        sql.append(",sku");
        sql.append(",matchid");
        sql.append(",quantity");
        sql.append(",tolocation");
        sql.append(",area");
        sql.append(",batchid");
        sql.append(",state");
        sql.append(",downdate");
        sql.append(",shopid");
        sql.append(",discount");
        sql.append(",barcode");
        sql.append(",goodsname");
        sql.append(",wmsboxcode");
        sql.append(",shopname");
        sql.append(",wmsorderid");
        sql.append(") values(");
        sql.append("?");
        sql.append(",?");
        sql.append(",?");
        sql.append(",?");
        sql.append(",?");
        sql.append(",?");
        sql.append(",?");
        sql.append(",?");
        sql.append(",?");
        sql.append(",?");
        sql.append(",?");
        sql.append(",?");
        sql.append(",?");
        sql.append(",?");
        sql.append(",?");
        sql.append(",?");
        sql.append(")");
        return sql.toString();
    }

    @Override
    @Transactional(rollbackFor = Exception.class, timeout = 300)
    public void btnDpsStorageCR(DpsZcServer dpsZcServer) throws Exception {
        // 下发到sqlserver数据库
        Connection conn = null;
        PreparedStatement ps = null;
        PreparedStatement psUpdateccr = null;
        ResultSet rs = null;
        try {
            conn = MssqlUtils.getConnection(dpsZcServer.getIp(), dpsZcServer.getPort(), dpsZcServer.getDbName(), dpsZcServer.getDbUser(), dpsZcServer.getDbPwd());
            conn.setAutoCommit(false);
            String tableCr = dpsZcServer.getDbTable()+"_CR";
            psUpdateccr = conn.prepareStatement(this.getUpdateMidOrdersCRSql(tableCr));
//            Set<String> delOrderSet = new HashSet<>();
            Map<String, List<DpsMidOrdersCRVo>> dpsMidOrdersCRMap = new HashMap<>();
            Map<String, String> orderTabMap = new HashMap<>();
            Map<String, Integer> dpsMidOrdersCRCntMap = new HashMap<>();

            ps = conn.prepareStatement(this.getSelectMidOrdersCRSql(tableCr));
            rs = ps.executeQuery();
            while (rs.next()) {
                DpsMidOrdersCRVo dpsMidOrdersCRObj = DpsMidOrdersCRVo
                        .builder()
                        .orderid(rs.getString("orderid"))
                        .sku(rs.getString("sku"))
                        .matchid(rs.getString("matchid"))
                        .quantity(rs.getInt("quantity"))
                        .tolocation(rs.getString("tolocation"))
                        .area(rs.getString("area"))
                        .state(rs.getString("state"))
                        .truequantity(rs.getInt("truequantity"))
                        .downdate(rs.getString("downdate"))
                        .oprationstate(rs.getString("oprationstate"))
                        .oprationtime(rs.getString("oprationtime"))
                        .shopid(rs.getString("shopid"))
                        .boxcode(rs.getString("boxcode"))
                        .barcode(rs.getString("barcode"))
                        .goodsname(rs.getString("goodsname"))
                        .tasktype(rs.getString("tasktype"))
                        .wmsboxcode(rs.getString("wmsboxcode"))
                        .shopname(rs.getString("shopname"))
                        .wmsorderid(rs.getString("wmsorderid"))
                        .build();

                orderTabMap.put(dpsMidOrdersCRObj.getWmsboxcode(), tableCr);
                // 若存在状态未完成的，直接删除 3
//                if (!"3".equals(dpsMidOrdersCRObj.getOprationstate())) {
//                    delOrderSet.add(dpsMidOrdersCRObj.getWmsboxcode());
//                }

                if (dpsMidOrdersCRMap.get(dpsMidOrdersCRObj.getWmsboxcode()) == null) {
                    List<DpsMidOrdersCRVo> dpsMidOrdersCRObjList = new ArrayList<>();
                    dpsMidOrdersCRObjList.add(dpsMidOrdersCRObj);
                    dpsMidOrdersCRMap.put(dpsMidOrdersCRObj.getWmsboxcode(), dpsMidOrdersCRObjList);
                    dpsMidOrdersCRCntMap.put(dpsMidOrdersCRObj.getWmsboxcode(),1);
                } else {
                    dpsMidOrdersCRMap.get(dpsMidOrdersCRObj.getWmsboxcode()).add(dpsMidOrdersCRObj);
                    dpsMidOrdersCRCntMap.put(dpsMidOrdersCRObj.getWmsboxcode(),dpsMidOrdersCRCntMap.get(dpsMidOrdersCRObj.getWmsboxcode()) + 1);
                }
            }

            //根据删除列表，删除对应的对象
//            for (String key : delOrderSet) {
//                dpsMidOrdersCRMap.remove(key);
//            }

            if(!dpsMidOrdersCRMap.isEmpty()){
                ps = conn.prepareStatement(this.getSelectMidOrderCnt(dpsZcServer.getDbTable(),dpsMidOrdersCRMap.keySet()));
                rs = ps.executeQuery();
                while(rs.next()){
                    String wmsboxcode = rs.getString("wmsboxcode");
                    int cnt = rs.getInt("cnt");
                    if(ToolUtil.isNotEmpty(dpsMidOrdersCRCntMap.get(wmsboxcode)) && dpsMidOrdersCRCntMap.get(wmsboxcode) != cnt){
                        dpsMidOrdersCRMap.remove(wmsboxcode);
                    }
                }
            }

            int ccrCnt = 0;
            for (String key : dpsMidOrdersCRMap.keySet()) {
                // 修改状态
                psUpdateccr.setString(1, key);
                psUpdateccr.addBatch();
                ccrCnt++;
                // 根据回调数据修改拣货任务
                for (DpsMidOrdersCRVo obj : dpsMidOrdersCRMap.get(key)) {
                    if (ToolUtil.isNotEmpty(obj.getWmsorderid())) {
                        this.hxStorageOutDetailedService.lambdaUpdate()
                                .eq(HxStorageOutDetailed::getId, obj.getWmsorderid())
                                .set(HxStorageOutDetailed::getRealNum, obj.getTruequantity())
                                .set(HxStorageOutDetailed::getStorageTime, obj.getOprationtime())
                                .set(HxStorageOutDetailed::getPicked, "是")
                                .update();
                    } else {
                        this.hxStorageOutDetailedService.lambdaUpdate()
                                .eq(HxStorageOutDetailed::getStorageNumber, obj.getWmsboxcode())
                                .eq(HxStorageOutDetailed::getGoodsNumber, obj.getSku())
                                .set(HxStorageOutDetailed::getRealNum, obj.getTruequantity())
                                .set(HxStorageOutDetailed::getStorageTime, obj.getOprationtime())
                                .set(HxStorageOutDetailed::getPicked, "是")
                                .update();
                    }

                }

                //修改拣货单状态
                HxStorageOutDetailedParam hxStorageOutDetailedParam = new HxStorageOutDetailedParam();
                hxStorageOutDetailedParam.setStorageNumber(key);
                ResponseData responseData = this.dpsCompleteStorage(hxStorageOutDetailedParam);
                if (!responseData.getSuccess()) {
                    throw new Exception(responseData.getMessage());
                }
            }
            if (ccrCnt > 0) {
                psUpdateccr.executeBatch();
            }
            conn.commit();
        } catch (SQLException e) {
            e.printStackTrace();
            JdbcUtls.rollback(conn);
            throw new Exception(e.getMessage());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            throw new Exception(e.getMessage());
        } finally {
            JdbcUtls.closePreparedStatement(psUpdateccr);
            JdbcUtls.closeAll(rs, ps, conn);
        }
    }

    private String getSelectMidOrderCnt(String tableName,Set<String> keyList){
        StringBuffer sql = new StringBuffer();
        sql.append("select ");
        sql.append("wmsboxcode");
        sql.append(",count(1) as cnt ");
        sql.append("from ").append(tableName).append(" ");
        sql.append("where wmsboxcode in (");
        int cnt = 0;
        for(String wmsboxcode : keyList){
            if(cnt == 0 ){
                sql.append("'").append(wmsboxcode).append("'");
            }else{
                sql.append(",'").append(wmsboxcode).append("'");
            }
            cnt++;
        }
        sql.append(") ");
        sql.append("group by wmsboxcode");
        return sql.toString();
    }


    private String getSelectMidOrdersCRSql(String tableName) {
        StringBuffer sql = new StringBuffer();
        sql.append("select orderid ");
        sql.append(",sku");
        sql.append(",matchid");
        sql.append(",quantity");
        sql.append(",tolocation");
        sql.append(",area");
        sql.append(",state");
        sql.append(",truequantity");
        sql.append(",downdate");
        sql.append(",oprationtime");
        sql.append(",oprationstate");
        sql.append(",shopid");
        sql.append(",boxcode");
        sql.append(",barcode");
        sql.append(",goodsname");
        sql.append(",tasktype");
        sql.append(",wmsboxcode");
        sql.append(",shopname ");
        sql.append(",wmsorderid ");
        sql.append("from ").append(tableName).append(" ");
        sql.append("where state = '3' ");
        return sql.toString();
    }

    private String getUpdateMidOrdersCRSql(String tableName) {
        StringBuffer sql = new StringBuffer();
        sql.append("update ").append(tableName).append(" ");
        sql.append("set state = '4' ");
        sql.append("where wmsboxcode = ? ");
        return sql.toString();
    }

    @Override
    public List<HxStorageOutResult> findAppAgvYilingquBySpec(HxStorageOutParam param) {
        return this.baseMapper.findAppAgvYilingquBySpec(param);
    }

    @Override
    public HxStorageOutResult findAppAgvYilingquBySpecJs(HxStorageOutParam hxStorageOutParam) {
        return this.baseMapper.findAppAgvYilingquBySpecJs(hxStorageOutParam);
    }

    @Override
    public List<StorageOutCntOby> areaStorageOutCntList(HxStorageOutParam hxStorageOutParam) {
        return this.baseMapper.areaStorageOutCntList(hxStorageOutParam);
    }

    @Override
    public List<HxStorageOutResult> expExcel(HxStorageOutParam param, String condition, Long operateId) {
        return this.baseMapper.expExcel(param,condition,operateId);
    }


    @Override
    @Transactional(rollbackFor = Exception.class, timeout = 180)
    public ResponseData AGVtaskIssued(Integer[] ids, User user) {

        try {
            List<HxStorageOut> hxStorageOuts = this.lambdaQuery()
                    .in(HxStorageOut::getId, ids).list();
            BasicCustomer basicCustomer = null;
            List<String> storageNumberList = new ArrayList<>();
            storageNumberList = hxStorageOuts.stream()
                    .map(HxStorageOut::getStorageNumber)
                    .collect(Collectors.toList());
            //查找拣货明细
            Map<String, List<HxStorageOutDetailed>> hxStorageOutDetailedMap = new HashMap<>();
            List<HxStorageOutDetailed> hxStorageOutDetaileds = hxStorageOutDetailedService.lambdaQuery()
                    .in(HxStorageOutDetailed::getStorageNumber, storageNumberList)
                    .list();
            List<HxStorageOutDetailed> _hxStorageOutDetailedList = null;
            for (HxStorageOutDetailed obj : hxStorageOutDetaileds) {
                if (hxStorageOutDetailedMap.get(obj.getStorageNumber()) == null) {
                    _hxStorageOutDetailedList = new ArrayList<>();
                    _hxStorageOutDetailedList.add(obj);
                    hxStorageOutDetailedMap.put(obj.getStorageNumber(), _hxStorageOutDetailedList);
                } else {
                    hxStorageOutDetailedMap.get(obj.getStorageNumber()).add(obj);
                }
            }
            //开始下发拣货任务
            List<AgvStorageTask> agvStorageTasks = new ArrayList<>();
            for (HxStorageOut obj : hxStorageOuts) {
                //创建AGV任务主表
                AgvStorageTask agvStorageTask = new AgvStorageTask();
                //主键
                agvStorageTask.setId(IdUtil.simpleUUID());
                //订单号
                agvStorageTask.setStorageNumber(obj.getStorageNumber());
                //任务编号
                agvStorageTask.setTaskNo(CodeGenerateUtil.generate());
                //AGV机器人类型
                if ("1".equals(obj.getAgvRobot())) { //海康
                    agvStorageTask.setAgvTyp("HIK");
                    //暂时写死 目标点
                    agvStorageTask.setWebCode(obj.getStockPort());
                } else if ("2".equals(obj.getAgvRobot())) { //TUSK
                    agvStorageTask.setAgvTyp("TUSK");
                    //暂时写死 目标点
                    agvStorageTask.setWebCode("H" + StringUtils.leftPad(obj.getStockPort(), 3, "0"));
                }
                //创建人
                if (user != null) {
                    agvStorageTask.setCreateUser(user.getAccount());
                }
                //基础URL
                if (basicCustomer != null && ToolUtil.isNotEmpty(basicCustomer.getAgvBaseUrl())) {
                    agvStorageTask.setAgvApiBaseUrl(basicCustomer.getAgvBaseUrl());
                }
                //创建时间
                agvStorageTask.setCreateTime(new Date());
                //交付客户id
                agvStorageTask.setDeliverId(obj.getDeliverId());
                //部门id
                agvStorageTask.setDeptId(obj.getDeptId());
                //发货仓库id
                agvStorageTask.setSetWarehouseId(obj.getSetWarehouseId());
                //是否拆托 默认否
                agvStorageTask.setDisPallet("否");
                //新增
                this.agvStorageTaskMapper.insert(agvStorageTask);
                agvStorageTasks.add(agvStorageTask);
                //明细
                List<AgvStorageTaskDetail> saveList = new ArrayList<>();
                AgvStorageTaskDetail agvStorageTaskDetail = null;
                for (HxStorageOutDetailed _obj : hxStorageOutDetailedMap.get(obj.getStorageNumber())) {
                    agvStorageTaskDetail = new AgvStorageTaskDetail();
                    agvStorageTaskDetail.setId(IdUtil.simpleUUID()); //主键
                    agvStorageTaskDetail.setStorageTaskId(agvStorageTask.getId()); //agv拣货任务ID
                    agvStorageTaskDetail.setStorageOutDetailId(_obj.getId().longValue()); //拣货明细ID
                    agvStorageTaskDetail.setPositionId(_obj.getPositionId()); //库位id
                    agvStorageTaskDetail.setPositionNumber(_obj.getPositionNumber());
                    agvStorageTaskDetail.setPositionPickingorder(Integer.valueOf(_obj.getPositionPickingorder()));
                    agvStorageTaskDetail.setGoodsId(_obj.getGoodsId());
                    agvStorageTaskDetail.setGoodsNumber(_obj.getGoodsNumber());
                    agvStorageTaskDetail.setGoodsName(_obj.getGoodsName());
                    agvStorageTaskDetail.setUnit(_obj.getUnit());
                    agvStorageTaskDetail.setRate(new BigDecimal(_obj.getRate()));
                    agvStorageTaskDetail.setNum(new BigDecimal(_obj.getNum()).setScale(3, BigDecimal.ROUND_HALF_UP));
                    saveList.add(agvStorageTaskDetail);
                }
                //批量保存
                if (saveList != null && saveList.size() > 0) {
                    this.agvStorageTaskDetailService.saveBatch(saveList);
                }

                HxStorageOutParam update = new HxStorageOutParam();
                update.setId(obj.getId());
                update.setStorageState("拣货中");
                update.setStorageUser("待绑定");
                update.setStorageUserName("待绑定");
                update.setAgvStorageTask("是");
                update.setStorageTime(new Date());
                this.update(update);
            }
            //批量呼叫小车
//            for (AgvStorageTask agvStorageTask : agvStorageTasks) {
//                //根据拣货单获取拣货单中未拣商品和对应库位
//                List<AgvStorageTaskDetailResult> agvStorageTaskDetailList = this.agvStorageTaskDetailMapper.getNextTaskGoodList(AgvStorageTaskDetailParam.builder()
//                        .storageTaskId(agvStorageTask.getId())
//                        .picked("否")
//                        .limit(" 1 ")
//                        .build());
//                AgvStorageTaskDetailResult agvStorageTaskDetail = agvStorageTaskDetailList.get(0);
//                /**
//                 * 根据库位编号，获取APR编号
//                 */
//                AgvStoragePosition agvStoragePosition = agvStoragePositionService.lambdaQuery()
//                        .eq(AgvStoragePosition::getSetWarehouseId, agvStorageTask.getSetWarehouseId())
//                        .eq(AgvStoragePosition::getPositionNumber, agvStorageTaskDetail.getPositionNumber())
//                        .one();
//                if(agvStoragePosition == null){
//                    throw new Exception("AGV拣货位["+agvStorageTaskDetail.getPositionNumber()+"]不存在！");
//                }
//                //如果是海康机器人
//                if ("HIK".equals(agvStorageTask.getAgvTyp())) {
//                    //封装接口信息
//                    HikAgvTaskParam param = new HikAgvTaskParam();
//                    param.setTaskNo(agvStorageTask.getTaskNo());
//                    param.setPositionType("1");
//                    param.setStartArea(agvStoragePosition.getAgvPick());
//                    param.setEndcargoInfo(agvStorageTaskDetail.getPositionNumber());
//                    HikRsVo hikRsVo = HikApiUtils.genctnrBinTask(agvStorageTask.getAgvApiBaseUrl(), param);
//                    if (hikRsVo == null) {
//                        throw new Exception("接口调用错误");
//                    } else if (!"0".equals(hikRsVo.getCode())) {
//                        throw new Exception(hikRsVo.getMessage());
//                    }
//                } else if ("TUSK".equals(agvStorageTask.getAgvTyp())) {
//                    CreateSortParam param = new CreateSortParam();
//                    param.setTaskId(agvStorageTask.getTaskNo());
//                    //取托盘
//                    param.getTargetActions().add(TargetActionsVo.builder()
//                            .target(agvStoragePosition.getAgvPick())
//                            .action("GET")
//                            .build());
//
//                    String positionNumber = null;
//                    if (agvStoragePosition != null) {
//                        positionNumber = agvStoragePosition.getAprCode();
//                    } else {
//                        positionNumber = agvStorageTaskDetail.getPositionNumber();
//                    }
//                    //取货点
//                    param.getTargetActions().add(TargetActionsVo.builder()
//                            .target(positionNumber)
//                            .action("MOVE")
//                            .build());
//                    TuskRsVo tuskRs = TustApiUtils.createSortTask(agvStorageTask.getAgvApiBaseUrl(), param);
//                    if (tuskRs == null) {
//                        throw new Exception("接口调用错误");
//                    } else if (tuskRs.getCode() != 200) {
//                        throw new Exception(tuskRs.getMsg());
//                    }
//                }
//                //修改拣货状态
//                AgvStorageTaskParam update = new AgvStorageTaskParam();
//                update.setId(agvStorageTask.getId());
//                update.setStat("10");
//                update.setCurrTask(agvStorageTaskDetail.getId());
//                agvStorageTaskService.update(update);
//            }
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); //手动回滚
            return ResponseData.error(e.getMessage());
        }

        return ResponseData.success();
    }

    /**
     * AGV扫码拣货任务下发
     *
     * @param ids
     * @param user
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class, timeout = 180)
    public ResponseData btnAgvStorageScan(Integer[] ids, User user) {
        if (ToolUtil.isEmpty(ids)) {
            return ResponseData.error("请先选择要操作的记录！");
        }
        List<HxStorageOut> hxStorageOuts = this.lambdaQuery()
                .in(HxStorageOut::getId, ids).list();
        BasicCustomer basicCustomer = null;
        Map<String, HxStorageOut> hxStorageOutMap = new HashMap<>();
        for (HxStorageOut obj : hxStorageOuts) {
            if (basicCustomer == null) {
                basicCustomer = basicCustomerService.getById(obj.getCustomerId());
            }
            if ("0".equals(basicCustomer.getBoxPickMode()) && (ToolUtil.isEmpty(obj.getPrintNumb()) || "0".equals(obj.getPrintNumb()))) {
                return ResponseData.error("请先打印任务[" + obj.getStorageNumber() + "]的标签");
            }
            if ("是".equals(obj.getAgvStorageTask())) {
                return ResponseData.error("任务[" + obj.getStorageNumber() + "]已下发，无法多次操作");
            }
            if (!"待拣货".equals(obj.getStorageState())) {
                return ResponseData.error("任务[" + obj.getStorageNumber() + "]状态不是[待拣货]，无法操作");
            }
            if (ToolUtil.isEmpty(obj.getStockPort())) {
                return ResponseData.error("任务[" + obj.getStorageNumber() + "]请先分配集货位！");
            }
            if ("是".equals(obj.getPalletStorageAreaFlag())) {
                return ResponseData.error("任务[" + obj.getStorageNumber() + "]是整托拣货任务，无法操作！");
            }
            hxStorageOutMap.put(obj.getStorageNumber(), obj);
        }

        // 循环列表 插入到任务列表中
        List<AgvStorageTaskList> addList = new ArrayList<>();
        AgvStorageTaskList agvStorageTaskListAdd = null;
        for (String storageNumber : hxStorageOutMap.keySet()) {
            agvStorageTaskListAdd = new AgvStorageTaskList();
            agvStorageTaskListAdd.setStorageId(hxStorageOutMap.get(storageNumber).getId().longValue());
            agvStorageTaskListAdd.setStorageNumber(hxStorageOutMap.get(storageNumber).getStorageNumber());
            agvStorageTaskListAdd.setAreaName(hxStorageOutMap.get(storageNumber).getAreaName());
            agvStorageTaskListAdd.setDeptId(hxStorageOutMap.get(storageNumber).getDeptId());
            agvStorageTaskListAdd.setCreateUser(user.getUserId());
            agvStorageTaskListAdd.setCreateTime(new Date());
            agvStorageTaskListAdd.setCreateUserName(user.getName());
            agvStorageTaskListAdd.setWarehouseId(hxStorageOutMap.get(storageNumber).getSetWarehouseId());
            agvStorageTaskListAdd.setWarehouseName(hxStorageOutMap.get(storageNumber).getSetWarehouse());
            addList.add(agvStorageTaskListAdd);

            HxStorageOutParam update = new HxStorageOutParam();
            update.setId(hxStorageOutMap.get(storageNumber).getId());
            update.setStorageState("拣货中");
            update.setStorageUser("待绑定");
            update.setStorageUserName("待绑定");
            update.setAgvStorageTask("是");
            update.setStorageTime(new Date());
            this.update(update);
        }

        if (addList.size() > 0) {
            agvStorageTaskListService.saveBatch(addList, 1000);
        }
        return ResponseData.success();
    }

    /**
     * 根据仓库ID，获取AGV未下发列表，然后进行下发
     *
     * @param warehouseId
     */
    @Override
    @Transactional(rollbackFor = Exception.class, timeout = 180)
    public ResponseData autoAgvTaskScan(Long warehouseId) {

        // 根据仓库ID，获取仓库下对应AGV配置。
        List<AgvAreaQuota> agvAreaQuotaList = agvAreaQuotaService.lambdaQuery()
                .eq(AgvAreaQuota::getWarehouseId, warehouseId)
                .list();
        if (ToolUtil.isEmpty(agvAreaQuotaList)) {
            return ResponseData.error("无仓库对应AGV配置！");
        }
        Map<String, AgvAreaQuota> agvAreaQuotaMap = new HashMap<>();
        for (AgvAreaQuota obj : agvAreaQuotaList) {
            if (obj.getAgvQuota() > obj.getAgvNum() && ToolUtil.isNotEmpty(obj.getAgvPauseZone())) {
                agvAreaQuotaMap.put(obj.getAreaName(), obj);
            }
        }
        // 根据仓库ID，获取已下发得agv任务列表。
        List<AgvStorageTaskList> agvStorageTaskList = agvStorageTaskListService.lambdaQuery()
                .eq(AgvStorageTaskList::getWarehouseId, warehouseId)
                .eq(AgvStorageTaskList::getErrRemark, "")
                .list();
        if (ToolUtil.isEmpty(agvStorageTaskList)) {
            return ResponseData.error("无仓库对应agv任务！");
        }
        Map<String, List<AgvStorageTaskList>> agvStorageTaskListMap = new HashMap<>();
        List<AgvStorageTaskList> agvStorageTaskListobjList;
        List<String> hxStorageNumList = new ArrayList<>();
        for (AgvStorageTaskList obj : agvStorageTaskList) {
            hxStorageNumList.add(obj.getStorageNumber());
            if (agvStorageTaskListMap.get(obj.getAreaName()) == null) {
                agvStorageTaskListobjList = new ArrayList<>();
                agvStorageTaskListobjList.add(obj);
                agvStorageTaskListMap.put(obj.getAreaName(), agvStorageTaskListobjList);
            } else {
                agvStorageTaskListMap.get(obj.getAreaName()).add(obj);
            }
        }

        BasicCustomer basicCustomer = null;
        // 根据拣货任务编号 获取对应的拣货任务
        List<HxStorageOut> hxStorageOutLists = hxStorageOutService.lambdaQuery()
                .in(HxStorageOut::getStorageNumber, hxStorageNumList)
                .list();
        Map<String, HxStorageOut> hxStorageOutMap = new HashMap<>();
        for (HxStorageOut obj : hxStorageOutLists) {
            if (basicCustomer == null) {
                basicCustomer = basicCustomerService.getById(obj.getCustomerId());
            }
            hxStorageOutMap.put(obj.getStorageNumber(), obj);
        }
        // 根据拣货任务编号 获取对应的拣货任务明细
        List<HxStorageOutDetailed> hxStorageOutDetailedList = hxStorageOutDetailedService.lambdaQuery()
                .in(HxStorageOutDetailed::getStorageNumber, hxStorageNumList)
                .list();
        Map<String, List<HxStorageOutDetailed>> hxStorageOutDetailedMap = new HashMap<>();
        List<HxStorageOutDetailed> hxStorageOutDetailedListAdd;
        for (HxStorageOutDetailed obj : hxStorageOutDetailedList) {
            if (hxStorageOutDetailedMap.get(obj.getStorageNumber()) == null) {
                hxStorageOutDetailedListAdd = new ArrayList<>();
                hxStorageOutDetailedListAdd.add(obj);
                hxStorageOutDetailedMap.put(obj.getStorageNumber(), hxStorageOutDetailedListAdd);
            } else {
                hxStorageOutDetailedMap.get(obj.getStorageNumber()).add(obj);
            }
        }

        // 根据 仓库下AGV的配置，循环给AGV下发任务。
        for (String areaName : agvAreaQuotaMap.keySet()) {
            AgvAreaQuota agvAreaQuota = agvAreaQuotaMap.get(areaName);
            // 获取该库区 应下发数量  限额 - 当前已有AGV
            int cnt = agvAreaQuota.getAgvQuota() - agvAreaQuota.getAgvNum();
            int agvAddCnt = 0;
            List<AgvStorageTaskList> agvStorageTaskLists = agvStorageTaskListMap.get(areaName);
            for (AgvStorageTaskList obj : agvStorageTaskLists) {
                agvAddCnt++;
                if (agvAddCnt > cnt) {
                    break;
                }

                HxStorageOut hxStorageOut = hxStorageOutMap.get(obj.getStorageNumber());
                //创建AGV任务主表
                AgvStorageTask agvStorageTask = new AgvStorageTask();
                //主键
                agvStorageTask.setId(IdUtil.simpleUUID());
                //订单号
                agvStorageTask.setStorageNumber(obj.getStorageNumber());
                //任务编号
                agvStorageTask.setTaskNo(CodeGenerateUtil.generate());
                //AGV机器人类型
                if ("1".equals(hxStorageOut.getAgvRobot())) { //海康
                    agvStorageTask.setAgvTyp("HIK");
                    //暂时写死 目标点
                    agvStorageTask.setWebCode(hxStorageOut.getStockPort());
                } else if ("2".equals(hxStorageOut.getAgvRobot())) { //TUSK
                    agvStorageTask.setAgvTyp("TUSK");
                    //暂时写死 目标点
                    agvStorageTask.setWebCode("H" + StringUtils.leftPad(hxStorageOut.getStockPort(), 3, "0"));
                }
                agvStorageTask.setCreateUser("任务下发");
                //基础URL
                if (basicCustomer != null && ToolUtil.isNotEmpty(basicCustomer.getAgvBaseUrl())) {
                    agvStorageTask.setAgvApiBaseUrl(basicCustomer.getAgvBaseUrl());
                }
                //创建时间
                agvStorageTask.setCreateTime(new Date());
                //交付客户id
                agvStorageTask.setDeliverId(hxStorageOut.getDeliverId());
                //部门id
                agvStorageTask.setDeptId(obj.getDeptId());
                //发货仓库id
                agvStorageTask.setSetWarehouseId(hxStorageOut.getSetWarehouseId());
                //是否拆托 默认否
                agvStorageTask.setDisPallet("否");

                // 下发小车
                //如果是海康机器人
                String errRemark = "";
                if ("HIK".equals(agvStorageTask.getAgvTyp())) {
                    //封装接口信息
                    HikAgvTaskParam param = new HikAgvTaskParam();
                    param.setTaskNo(agvStorageTask.getTaskNo());
                    param.setPositionType("1");
                    param.setStartArea(agvAreaQuota.getTrayZone());
                    param.setEndcargoInfo(agvAreaQuota.getAgvPauseZone());
                    HikRsVo hikRsVo = HikApiUtils.genctnrBinTask(agvStorageTask.getAgvApiBaseUrl(), param);
                    if (hikRsVo == null) {
                        errRemark = "接口调用错误";
                    } else if (!"0".equals(hikRsVo.getCode())) {
                        errRemark = hikRsVo.getMessage();
                    }
                } else if ("TUSK".equals(agvStorageTask.getAgvTyp())) {
                    CreateSortParam param = new CreateSortParam();
                    param.setTaskId(agvStorageTask.getTaskNo());
                    //取托盘
                    param.getTargetActions().add(TargetActionsVo.builder()
                            .target(agvAreaQuota.getTrayZone())
                            .action("GET")
                            .build());

                    //取货点
                    param.getTargetActions().add(TargetActionsVo.builder()
                            .target(agvAreaQuota.getAgvPauseZone())
                            .action("MOVE")
                            .build());
                    TuskRsVo tuskRs = TustApiUtils.createSortTask(agvStorageTask.getAgvApiBaseUrl(), param);
                    if (tuskRs == null) {
                        errRemark = "接口调用错误";
                    } else if (tuskRs.getCode() != 200) {
                        errRemark = tuskRs.getMsg();
                    }
                }
                //如果下发成功 则删除任务，如果没有下发成功 则标记失败原因
                if (ToolUtil.isEmpty(errRemark)) {
                    agvStorageTaskListService.removeById(obj.getId());
                } else {
                    agvStorageTaskListService.lambdaUpdate()
                            .set(AgvStorageTaskList::getErrRemark, errRemark)
                            .eq(AgvStorageTaskList::getId, obj.getId())
                            .update();
                    agvAddCnt--;
                    continue;
                }

                //新增
                this.agvStorageTaskMapper.insert(agvStorageTask);
                //明细
                List<AgvStorageTaskDetail> saveList = new ArrayList<>();
                AgvStorageTaskDetail agvStorageTaskDetail = null;
                for (HxStorageOutDetailed _obj : hxStorageOutDetailedMap.get(obj.getStorageNumber())) {
                    agvStorageTaskDetail = new AgvStorageTaskDetail();
                    agvStorageTaskDetail.setId(IdUtil.simpleUUID()); //主键
                    agvStorageTaskDetail.setStorageTaskId(agvStorageTask.getId()); //agv拣货任务ID
                    agvStorageTaskDetail.setStorageOutDetailId(_obj.getId().longValue()); //拣货明细ID
                    agvStorageTaskDetail.setPositionId(_obj.getPositionId()); //库位id
                    agvStorageTaskDetail.setPositionNumber(_obj.getPositionNumber());
                    agvStorageTaskDetail.setPositionPickingorder(Integer.valueOf(_obj.getPositionPickingorder()));
                    agvStorageTaskDetail.setGoodsId(_obj.getGoodsId());
                    agvStorageTaskDetail.setGoodsNumber(_obj.getGoodsNumber());
                    agvStorageTaskDetail.setGoodsName(_obj.getGoodsName());
                    agvStorageTaskDetail.setUnit(_obj.getUnit());
                    agvStorageTaskDetail.setRate(new BigDecimal(_obj.getRate()));
                    agvStorageTaskDetail.setNum(new BigDecimal(_obj.getNum()).setScale(3, BigDecimal.ROUND_HALF_UP));
                    saveList.add(agvStorageTaskDetail);
                }
                //批量保存
                if (saveList != null && saveList.size() > 0) {
                    this.agvStorageTaskDetailService.saveBatch(saveList);
                }

            }

            // 修改对应库区，已下发的AGV任务
            this.agvAreaQuotaService.lambdaUpdate()
                    .setSql("agv_num = agv_num + " + agvAddCnt)
                    .eq(AgvAreaQuota::getId, agvAreaQuota.getId())
                    .update();
        }
        return ResponseData.success();

    }

    /**
     * 下发任务
     *
     * @param user
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class, timeout = 180)
    public ResponseData issueTask(SueTaskIby sueTaskIby, User user) {
        HxStorageOutParam param = new HxStorageOutParam();
        param.setDeptId(user.getDeptId());
        if (ToolUtil.isNotEmpty(user.getOperateId())) {
            param.setOperateId(user.getOperateId());
        }
        param.setStorageState("待拣货");
        param.setAreaName(sueTaskIby.getAreaName());
        param.setLimitCnt(sueTaskIby.getSendingNum());
        List<HxStorageOutResult> hxStorageOutResultList = this.hxStorageOutService.findListBySpec(param);
        if (ToolUtil.isEmpty(hxStorageOutResultList)) {
            return ResponseData.error("无待下发的拣货任务！");
        }

        List<Integer> idList = new ArrayList<>();
        for (HxStorageOutResult obj : hxStorageOutResultList) {
            idList.add(obj.getId());
        }
        return this.btnAgvStorageScan(idList.toArray(new Integer[idList.size()]), user);
    }
}
